diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs index 995ab5bd86e..cbea5cd158e 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs @@ -129,7 +129,11 @@ impl<'a> Interpreter<'a> { self.define_pattern(parameter, typ, argument, arg_location)?; } - let function_body = self.interner.function(&function).as_expr(); + let function_body = self.interner.function(&function).try_as_expr().ok_or_else(|| { + let function = self.interner.function_name(&function).to_owned(); + InterpreterError::NonComptimeFnCallInSameCrate { function, location } + })?; + let result = self.evaluate(function_body)?; self.exit_function(previous_state); diff --git a/compiler/noirc_frontend/src/hir/comptime/scan.rs b/compiler/noirc_frontend/src/hir/comptime/scan.rs index f9cc54ef9e4..2ce22ab51e3 100644 --- a/compiler/noirc_frontend/src/hir/comptime/scan.rs +++ b/compiler/noirc_frontend/src/hir/comptime/scan.rs @@ -43,11 +43,12 @@ impl<'interner> Interpreter<'interner> { return Ok(()); } - let function = self.interner.function(&function); + if let Some(function) = self.interner.function(&function).try_as_expr() { + let state = self.enter_function(); + self.scan_expression(function)?; + self.exit_function(state); + } - let state = self.enter_function(); - self.scan_expression(function.as_expr())?; - self.exit_function(state); Ok(()) } diff --git a/compiler/noirc_frontend/src/hir_def/expr.rs b/compiler/noirc_frontend/src/hir_def/expr.rs index ab2344746d1..d498f2e1cfc 100644 --- a/compiler/noirc_frontend/src/hir_def/expr.rs +++ b/compiler/noirc_frontend/src/hir_def/expr.rs @@ -40,13 +40,6 @@ pub enum HirExpression { Error, } -impl HirExpression { - /// Returns an empty block expression - pub const fn empty_block() -> HirExpression { - HirExpression::Block(HirBlockExpression { statements: vec![] }) - } -} - /// Corresponds to a variable in the source code #[derive(Debug, Clone)] pub struct HirIdent { diff --git a/compiler/noirc_frontend/src/hir_def/function.rs b/compiler/noirc_frontend/src/hir_def/function.rs index e666f996231..dc563a5f65f 100644 --- a/compiler/noirc_frontend/src/hir_def/function.rs +++ b/compiler/noirc_frontend/src/hir_def/function.rs @@ -10,26 +10,30 @@ use crate::macros_api::{BlockExpression, StructId}; use crate::node_interner::{ExprId, NodeInterner, TraitImplId}; use crate::{ResolvedGeneric, Type}; -/// A Hir function is a block expression -/// with a list of statements +/// A Hir function is a block expression with a list of statements. +/// If the function has yet to be resolved, the body starts off empty (None). #[derive(Debug, Clone)] -pub struct HirFunction(ExprId); +pub struct HirFunction(Option); impl HirFunction { pub fn empty() -> HirFunction { - HirFunction(ExprId::empty_block_id()) + HirFunction(None) } pub const fn unchecked_from_expr(expr_id: ExprId) -> HirFunction { - HirFunction(expr_id) + HirFunction(Some(expr_id)) } - pub const fn as_expr(&self) -> ExprId { + pub fn as_expr(&self) -> ExprId { + self.0.expect("Function has yet to be elaborated, cannot get an ExprId of its body!") + } + + pub fn try_as_expr(&self) -> Option { self.0 } pub fn block(&self, interner: &NodeInterner) -> HirBlockExpression { - match interner.expression(&self.0) { + match interner.expression(&self.as_expr()) { HirExpression::Block(block_expr) => block_expr, _ => unreachable!("ice: functions can only be block expressions"), } diff --git a/compiler/noirc_frontend/src/node_interner.rs b/compiler/noirc_frontend/src/node_interner.rs index 5ed4ad85a58..1c7d0984b2f 100644 --- a/compiler/noirc_frontend/src/node_interner.rs +++ b/compiler/noirc_frontend/src/node_interner.rs @@ -386,11 +386,6 @@ impl StmtId { #[derive(Debug, Eq, PartialEq, Hash, Copy, Clone, PartialOrd, Ord)] pub struct ExprId(Index); -impl ExprId { - pub fn empty_block_id() -> ExprId { - ExprId(Index::unsafe_zeroed()) - } -} #[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)] pub struct FuncId(Index); @@ -558,7 +553,7 @@ pub struct QuotedTypeId(noirc_arena::Index); impl Default for NodeInterner { fn default() -> Self { - let mut interner = NodeInterner { + NodeInterner { nodes: Arena::default(), func_meta: HashMap::new(), function_definition_ids: HashMap::new(), @@ -598,12 +593,7 @@ impl Default for NodeInterner { reference_graph: petgraph::graph::DiGraph::new(), reference_graph_indices: HashMap::new(), reference_modules: HashMap::new(), - }; - - // An empty block expression is used often, we add this into the `node` on startup - let expr_id = interner.push_expr(HirExpression::empty_block()); - assert_eq!(expr_id, ExprId::empty_block_id()); - interner + } } }