From 3153058a780444622c5628caf4c18f50999c0e7b Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Mon, 20 Jan 2025 16:13:17 -0300 Subject: [PATCH 1/2] fix: proper cleanup when breaking from comptime loop on error --- .../src/hir/comptime/interpreter.rs | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs index d48a27c4181..28182e3dfe1 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs @@ -1724,6 +1724,8 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { let (end, _) = get_index(self, for_.end_range)?; let was_in_loop = std::mem::replace(&mut self.in_loop, true); + let mut result = Ok(Value::Unit); + for i in start..end { self.push_scope(); self.current_scope_mut().insert(for_.identifier.id, make_value(i)); @@ -1732,20 +1734,24 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { Ok(_) => (), Err(InterpreterError::Break) => break, Err(InterpreterError::Continue) => continue, - Err(other) => return Err(other), + Err(error) => { + result = Err(error); + break; + } } self.pop_scope(); } self.in_loop = was_in_loop; - Ok(Value::Unit) + result } fn evaluate_loop(&mut self, expr: ExprId) -> IResult { let was_in_loop = std::mem::replace(&mut self.in_loop, true); let in_lsp = self.elaborator.interner.is_in_lsp_mode(); let mut counter = 0; + let mut result = Ok(Value::Unit); loop { self.push_scope(); @@ -1754,7 +1760,10 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { Ok(_) => (), Err(InterpreterError::Break) => break, Err(InterpreterError::Continue) => continue, - Err(other) => return Err(other), + Err(error) => { + result = Err(error); + break; + } } self.pop_scope(); @@ -1762,12 +1771,13 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { counter += 1; if in_lsp && counter == 10_000 { let location = self.elaborator.interner.expr_location(&expr); - return Err(InterpreterError::LoopHaltedForUiResponsiveness { location }); + result = Err(InterpreterError::LoopHaltedForUiResponsiveness { location }); + break; } } self.in_loop = was_in_loop; - Ok(Value::Unit) + result } fn evaluate_break(&mut self, id: StmtId) -> IResult { From 0354c2c183cb99b2b75f8b7799188d0f955ecef4 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig Date: Mon, 20 Jan 2025 17:53:31 -0300 Subject: [PATCH 2/2] Keep track of whether we must break or not --- .../src/hir/comptime/interpreter.rs | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/comptime/interpreter.rs b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs index 28182e3dfe1..7eafdf1e71f 100644 --- a/compiler/noirc_frontend/src/hir/comptime/interpreter.rs +++ b/compiler/noirc_frontend/src/hir/comptime/interpreter.rs @@ -1730,17 +1730,21 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { self.push_scope(); self.current_scope_mut().insert(for_.identifier.id, make_value(i)); - match self.evaluate(for_.block) { - Ok(_) => (), - Err(InterpreterError::Break) => break, - Err(InterpreterError::Continue) => continue, + let must_break = match self.evaluate(for_.block) { + Ok(_) => false, + Err(InterpreterError::Break) => true, + Err(InterpreterError::Continue) => false, Err(error) => { result = Err(error); - break; + true } - } + }; self.pop_scope(); + + if must_break { + break; + } } self.in_loop = was_in_loop; @@ -1756,18 +1760,22 @@ impl<'local, 'interner> Interpreter<'local, 'interner> { loop { self.push_scope(); - match self.evaluate(expr) { - Ok(_) => (), - Err(InterpreterError::Break) => break, - Err(InterpreterError::Continue) => continue, + let must_break = match self.evaluate(expr) { + Ok(_) => false, + Err(InterpreterError::Break) => true, + Err(InterpreterError::Continue) => false, Err(error) => { result = Err(error); - break; + true } - } + }; self.pop_scope(); + if must_break { + break; + } + counter += 1; if in_lsp && counter == 10_000 { let location = self.elaborator.interner.expr_location(&expr);