diff --git a/compiler/noirc_evaluator/src/ssa.rs b/compiler/noirc_evaluator/src/ssa.rs index f9fd5f41f77..edc32fddeaf 100644 --- a/compiler/noirc_evaluator/src/ssa.rs +++ b/compiler/noirc_evaluator/src/ssa.rs @@ -61,6 +61,9 @@ pub(crate) fn optimize_into_acir( .run_pass(Ssa::remove_bit_shifts, "After Removing Bit Shifts:") // Run mem2reg once more with the flattened CFG to catch any remaining loads/stores .run_pass(Ssa::mem2reg, "After Mem2Reg:") + // Run the inlining pass again to handle functions with `InlineType::NoPredicates`. + // Before flattening is run, we treat functions marked with the `InlineType::NoPredicates` as an entry point. + .run_pass(Ssa::inline_functions_with_no_predicates, "After Inlining:") .run_pass(Ssa::fold_constants, "After Constant Folding:") .run_pass(Ssa::remove_enable_side_effects, "After EnableSideEffects removal:") .run_pass(Ssa::fold_constants_using_constraints, "After Constraint Folding:") diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs index 63d1c1b564f..16680c2b7eb 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/mod.rs @@ -390,7 +390,10 @@ impl<'a> Context<'a> { panic!("ACIR function should have been inlined earlier if not marked otherwise"); } } - InlineType::Fold | InlineType::Never => {} + InlineType::NoPredicates => { + panic!("All ACIR functions marked with #[no_predicates] should be inlined before ACIR gen. This is an SSA exclusive codegen attribute"); + } + InlineType::Fold => {} } // We only want to convert entry point functions. This being `main` and those marked with `InlineType::Fold` Ok(Some(self.convert_acir_main(function, ssa, brillig)?)) @@ -2653,10 +2656,14 @@ mod test { basic_call_with_outputs_assert(InlineType::Fold); call_output_as_next_call_input(InlineType::Fold); basic_nested_call(InlineType::Fold); + } - call_output_as_next_call_input(InlineType::Never); - basic_nested_call(InlineType::Never); - basic_call_with_outputs_assert(InlineType::Never); + #[test] + #[should_panic] + fn basic_calls_no_predicates() { + call_output_as_next_call_input(InlineType::NoPredicates); + basic_nested_call(InlineType::NoPredicates); + basic_call_with_outputs_assert(InlineType::NoPredicates); } #[test] @@ -2795,7 +2802,7 @@ mod test { let (acir_functions, _) = ssa .into_acir(&Brillig::default(), noirc_frontend::ast::Distinctness::Distinct) .expect("Should compile manually written SSA into ACIR"); - // The expected result should look very similar to the abvoe test expect that the input witnesses of the `Call` + // The expected result should look very similar to the above test expect that the input witnesses of the `Call` // opcodes will be different. The changes can discerned from the checks below. let main_acir = &acir_functions[0]; diff --git a/compiler/noirc_evaluator/src/ssa/ir/function.rs b/compiler/noirc_evaluator/src/ssa/ir/function.rs index 057786bf5ec..a49e02b0380 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/function.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/function.rs @@ -85,6 +85,13 @@ impl Function { self.runtime = runtime; } + pub(crate) fn is_no_predicates(&self) -> bool { + match self.runtime() { + RuntimeType::Acir(inline_type) => matches!(inline_type, InlineType::NoPredicates), + RuntimeType::Brillig => false, + } + } + /// Retrieves the entry block of a function. /// /// A function's entry block contains the instructions diff --git a/compiler/noirc_evaluator/src/ssa/opt/inlining.rs b/compiler/noirc_evaluator/src/ssa/opt/inlining.rs index 0b78d47fbb1..bddfb25f26c 100644 --- a/compiler/noirc_evaluator/src/ssa/opt/inlining.rs +++ b/compiler/noirc_evaluator/src/ssa/opt/inlining.rs @@ -36,13 +36,30 @@ impl Ssa { /// changes. This is because if the function's id later becomes known by a later /// pass, we would need to re-run all of inlining anyway to inline it, so we might /// as well save the work for later instead of performing it twice. + /// + /// There are some attributes that allow inlining a function at a different step of codegen. + /// Currently this is just `InlineType::NoPredicates` for which we have a flag indicating + /// whether treating that inline functions. The default is to treat these functions as entry points. #[tracing::instrument(level = "trace", skip(self))] - pub(crate) fn inline_functions(mut self) -> Ssa { - self.functions = btree_map(get_entry_point_functions(&self), |entry_point| { - let new_function = InlineContext::new(&self, entry_point).inline_all(&self); - (entry_point, new_function) - }); + pub(crate) fn inline_functions(self) -> Ssa { + Self::inline_functions_inner(self, true) + } + + // Run the inlining pass where functions marked with `InlineType::NoPredicates` as not entry points + pub(crate) fn inline_functions_with_no_predicates(self) -> Ssa { + Self::inline_functions_inner(self, false) + } + fn inline_functions_inner(mut self, no_predicates_is_entry_point: bool) -> Ssa { + self.functions = btree_map( + get_entry_point_functions(&self, no_predicates_is_entry_point), + |entry_point| { + let new_function = + InlineContext::new(&self, entry_point, no_predicates_is_entry_point) + .inline_all(&self); + (entry_point, new_function) + }, + ); self } } @@ -60,6 +77,8 @@ struct InlineContext { // The FunctionId of the entry point function we're inlining into in the old, unmodified Ssa. entry_point: FunctionId, + + no_predicates_is_entry_point: bool, } /// The per-function inlining context contains information that is only valid for one function. @@ -97,10 +116,19 @@ struct PerFunctionContext<'function> { /// should be left in the final program. /// This is the `main` function, any Acir functions with a [fold inline type][InlineType::Fold], /// and any brillig functions used. -fn get_entry_point_functions(ssa: &Ssa) -> BTreeSet { +fn get_entry_point_functions( + ssa: &Ssa, + no_predicates_is_entry_point: bool, +) -> BTreeSet { let functions = ssa.functions.iter(); let mut entry_points = functions - .filter(|(_, function)| function.runtime().is_entry_point()) + .filter(|(_, function)| { + // If we have not already finished the flattening pass, functions marked + // to not have predicates should be marked as entry points. + let no_predicates_is_entry_point = + no_predicates_is_entry_point && function.is_no_predicates(); + function.runtime().is_entry_point() || no_predicates_is_entry_point + }) .map(|(id, _)| *id) .collect::>(); @@ -114,11 +142,21 @@ impl InlineContext { /// The function being inlined into will always be the main function, although it is /// actually a copy that is created in case the original main is still needed from a function /// that could not be inlined calling it. - fn new(ssa: &Ssa, entry_point: FunctionId) -> InlineContext { + fn new( + ssa: &Ssa, + entry_point: FunctionId, + no_predicates_is_entry_point: bool, + ) -> InlineContext { let source = &ssa.functions[&entry_point]; let mut builder = FunctionBuilder::new(source.name().to_owned(), entry_point); builder.set_runtime(source.runtime()); - Self { builder, recursion_level: 0, entry_point, call_stack: CallStack::new() } + Self { + builder, + recursion_level: 0, + entry_point, + call_stack: CallStack::new(), + no_predicates_is_entry_point, + } } /// Start inlining the entry point function and all functions reachable from it. @@ -351,11 +389,17 @@ impl<'function> PerFunctionContext<'function> { for id in block.instructions() { match &self.source_function.dfg[*id] { Instruction::Call { func, arguments } => match self.get_function(*func) { - Some(function) => { - if ssa.functions[&function].runtime().is_entry_point() { + Some(func_id) => { + let function = &ssa.functions[&func_id]; + // If we have not already finished the flattening pass, functions marked + // to not have predicates should be marked as entry points. + let no_predicates_is_entry_point = + self.context.no_predicates_is_entry_point + && function.is_no_predicates(); + if function.runtime().is_entry_point() || no_predicates_is_entry_point { self.push_instruction(*id); } else { - self.inline_function(ssa, *id, function, arguments); + self.inline_function(ssa, *id, func_id, arguments); } } None => self.push_instruction(*id), diff --git a/compiler/noirc_frontend/src/ast/function.rs b/compiler/noirc_frontend/src/ast/function.rs index 9115178671e..dc426a4642a 100644 --- a/compiler/noirc_frontend/src/ast/function.rs +++ b/compiler/noirc_frontend/src/ast/function.rs @@ -109,7 +109,7 @@ impl From for NoirFunction { Some(FunctionAttribute::Oracle(_)) => FunctionKind::Oracle, Some(FunctionAttribute::Recursive) => FunctionKind::Recursive, Some(FunctionAttribute::Fold) => FunctionKind::Normal, - Some(FunctionAttribute::Inline(_)) => FunctionKind::Normal, + Some(FunctionAttribute::NoPredicates) => FunctionKind::Normal, None => FunctionKind::Normal, }; diff --git a/compiler/noirc_frontend/src/hir/resolution/errors.rs b/compiler/noirc_frontend/src/hir/resolution/errors.rs index 1727471c34f..953edc7c7d9 100644 --- a/compiler/noirc_frontend/src/hir/resolution/errors.rs +++ b/compiler/noirc_frontend/src/hir/resolution/errors.rs @@ -90,8 +90,8 @@ pub enum ResolverError { MutableGlobal { span: Span }, #[error("Self-referential structs are not supported")] SelfReferentialStruct { span: Span }, - #[error("#[inline(tag)] attribute is only allowed on constrained functions")] - InlineAttributeOnUnconstrained { ident: Ident }, + #[error("#[no_predicates] attribute is only allowed on constrained functions")] + NoPredicatesAttributeOnUnconstrained { ident: Ident }, #[error("#[fold] attribute is only allowed on constrained functions")] FoldAttributeOnUnconstrained { ident: Ident }, } @@ -362,16 +362,16 @@ impl<'a> From<&'a ResolverError> for Diagnostic { *span, ) }, - ResolverError::InlineAttributeOnUnconstrained { ident } => { + ResolverError::NoPredicatesAttributeOnUnconstrained { ident } => { let name = &ident.0.contents; let mut diag = Diagnostic::simple_error( - format!("misplaced #[inline(tag)] attribute on unconstrained function {name}. Only allowed on constrained functions"), - "misplaced #[inline(tag)] attribute".to_string(), + format!("misplaced #[no_predicates] attribute on unconstrained function {name}. Only allowed on constrained functions"), + "misplaced #[no_predicates] attribute".to_string(), ident.0.span(), ); - diag.add_note("The `#[inline(tag)]` attribute specifies to the compiler whether it should diverge from auto-inlining constrained functions".to_owned()); + diag.add_note("The `#[no_predicates]` attribute specifies to the compiler whether it should diverge from auto-inlining constrained functions".to_owned()); diag } ResolverError::FoldAttributeOnUnconstrained { ident } => { diff --git a/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/compiler/noirc_frontend/src/hir/resolution/resolver.rs index bef0ebdaacc..14a45a8788f 100644 --- a/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -1000,11 +1000,11 @@ impl<'a> Resolver<'a> { let name_ident = HirIdent::non_trait_method(id, location); let attributes = func.attributes().clone(); - let has_inline_attribute = attributes.is_inline(); + let has_no_predicates_attribute = attributes.is_no_predicates(); let should_fold = attributes.is_foldable(); if !self.inline_attribute_allowed(func) { - if has_inline_attribute { - self.push_err(ResolverError::InlineAttributeOnUnconstrained { + if has_no_predicates_attribute { + self.push_err(ResolverError::NoPredicatesAttributeOnUnconstrained { ident: func.name_ident().clone(), }); } else if should_fold { @@ -1013,10 +1013,10 @@ impl<'a> Resolver<'a> { }); } } - // Both the #[fold] and #[inline(tag)] alter a function's inline type and code generation in similar ways. + // Both the #[fold] and #[no_predicates] alter a function's inline type and code generation in similar ways. // In certain cases such as type checking (for which the following flag will be used) both attributes // indicate we should code generate in the same way. Thus, we unify the attributes into one flag here. - let has_inline_or_fold_attribute = has_inline_attribute || should_fold; + let has_inline_attribute = has_no_predicates_attribute || should_fold; let mut generics = vecmap(&self.generics, |(_, typevar, _)| typevar.clone()); let mut parameters = vec![]; @@ -1111,7 +1111,7 @@ impl<'a> Resolver<'a> { has_body: !func.def.body.is_empty(), trait_constraints: self.resolve_trait_constraints(&func.def.where_clause), is_entry_point: self.is_entry_point_function(func), - has_inline_or_fold_attribute, + has_inline_attribute, } } diff --git a/compiler/noirc_frontend/src/hir/type_check/mod.rs b/compiler/noirc_frontend/src/hir/type_check/mod.rs index 6235fe3848d..ef5692abdd3 100644 --- a/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -173,7 +173,7 @@ fn check_if_type_is_valid_for_program_input( ) { let meta = type_checker.interner.function_meta(&func_id); if (meta.is_entry_point && !param.1.is_valid_for_program_input()) - || (meta.has_inline_or_fold_attribute && !param.1.is_valid_non_inlined_function_input()) + || (meta.has_inline_attribute && !param.1.is_valid_non_inlined_function_input()) { let span = param.0.span(); errors.push(TypeCheckError::InvalidTypeForEntryPoint { span }); @@ -546,7 +546,7 @@ pub mod test { trait_constraints: Vec::new(), direct_generics: Vec::new(), is_entry_point: true, - has_inline_or_fold_attribute: false, + has_inline_attribute: false, }; interner.push_fn_meta(func_meta, func_id); diff --git a/compiler/noirc_frontend/src/hir_def/function.rs b/compiler/noirc_frontend/src/hir_def/function.rs index 57d3038a135..db54a40c8e7 100644 --- a/compiler/noirc_frontend/src/hir_def/function.rs +++ b/compiler/noirc_frontend/src/hir_def/function.rs @@ -126,8 +126,9 @@ pub struct FuncMeta { pub is_entry_point: bool, /// True if this function is marked with an attribute - /// that indicates it should not be inlined, such as `fold` or `inline(never)` - pub has_inline_or_fold_attribute: bool, + /// that indicates it should be inlined differently than the default (inline everything). + /// For example, such as `fold` (never inlined) or `no_predicates` (inlined after flattening) + pub has_inline_attribute: bool, } impl FuncMeta { diff --git a/compiler/noirc_frontend/src/lexer/token.rs b/compiler/noirc_frontend/src/lexer/token.rs index 82e17ac3912..ebbc7fc9813 100644 --- a/compiler/noirc_frontend/src/lexer/token.rs +++ b/compiler/noirc_frontend/src/lexer/token.rs @@ -582,8 +582,8 @@ impl Attributes { self.function.as_ref().map_or(false, |func_attribute| func_attribute.is_foldable()) } - pub fn is_inline(&self) -> bool { - self.function.as_ref().map_or(false, |func_attribute| func_attribute.is_inline()) + pub fn is_no_predicates(&self) -> bool { + self.function.as_ref().map_or(false, |func_attribute| func_attribute.is_no_predicates()) } } @@ -645,10 +645,7 @@ impl Attribute { ["test"] => Attribute::Function(FunctionAttribute::Test(TestScope::None)), ["recursive"] => Attribute::Function(FunctionAttribute::Recursive), ["fold"] => Attribute::Function(FunctionAttribute::Fold), - ["inline", tag] => { - validate(tag)?; - Attribute::Function(FunctionAttribute::Inline(tag.to_string())) - } + ["no_predicates"] => Attribute::Function(FunctionAttribute::NoPredicates), ["test", name] => { validate(name)?; let malformed_scope = @@ -701,7 +698,7 @@ pub enum FunctionAttribute { Test(TestScope), Recursive, Fold, - Inline(String), + NoPredicates, } impl FunctionAttribute { @@ -738,8 +735,8 @@ impl FunctionAttribute { /// Check whether we have an `inline` attribute /// Although we also do not want to inline foldable functions, /// we keep the two attributes distinct for clarity. - pub fn is_inline(&self) -> bool { - matches!(self, FunctionAttribute::Inline(_)) + pub fn is_no_predicates(&self) -> bool { + matches!(self, FunctionAttribute::NoPredicates) } } @@ -752,7 +749,7 @@ impl fmt::Display for FunctionAttribute { FunctionAttribute::Oracle(ref k) => write!(f, "#[oracle({k})]"), FunctionAttribute::Recursive => write!(f, "#[recursive]"), FunctionAttribute::Fold => write!(f, "#[fold]"), - FunctionAttribute::Inline(ref k) => write!(f, "#[inline({k})]"), + FunctionAttribute::NoPredicates => write!(f, "#[no_predicates]"), } } } @@ -798,7 +795,7 @@ impl AsRef for FunctionAttribute { FunctionAttribute::Test { .. } => "", FunctionAttribute::Recursive => "", FunctionAttribute::Fold => "", - FunctionAttribute::Inline(string) => string, + FunctionAttribute::NoPredicates => "", } } } diff --git a/compiler/noirc_frontend/src/monomorphization/ast.rs b/compiler/noirc_frontend/src/monomorphization/ast.rs index dc43f53e038..721c7d5f0b1 100644 --- a/compiler/noirc_frontend/src/monomorphization/ast.rs +++ b/compiler/noirc_frontend/src/monomorphization/ast.rs @@ -213,10 +213,13 @@ pub enum InlineType { Inline, /// Functions marked as foldable will not be inlined and compiled separately into ACIR Fold, - /// Similar to `Fold`, these functions will not be inlined and compile separately into ACIR. - /// They are different from `Fold` though as they are expected to be inlined into the program + /// Functions marked to have no predicates will not be inlined in the default inlining pass + /// and will be separately inlined after the flattening pass. + /// They are different from `Fold` as they are expected to be inlined into the program /// entry point before being used in the backend. - Never, + /// This attribute is unsafe and can cause a function whose logic relies on predicates from + /// the flattening pass to fail. + NoPredicates, } impl From<&Attributes> for InlineType { @@ -224,13 +227,7 @@ impl From<&Attributes> for InlineType { attributes.function.as_ref().map_or(InlineType::default(), |func_attribute| { match func_attribute { FunctionAttribute::Fold => InlineType::Fold, - FunctionAttribute::Inline(tag) => { - if tag == "never" { - InlineType::Never - } else { - InlineType::default() - } - } + FunctionAttribute::NoPredicates => InlineType::NoPredicates, _ => InlineType::default(), } }) @@ -242,7 +239,7 @@ impl InlineType { match self { InlineType::Inline => false, InlineType::Fold => true, - InlineType::Never => true, + InlineType::NoPredicates => false, } } } @@ -252,7 +249,7 @@ impl std::fmt::Display for InlineType { match self { InlineType::Inline => write!(f, "inline"), InlineType::Fold => write!(f, "fold"), - InlineType::Never => write!(f, "inline(never)"), + InlineType::NoPredicates => write!(f, "no_predicates"), } } } diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index b2cc7eee9f8..5f99e9e347a 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -1378,9 +1378,10 @@ fn lambda$f1(mut env$l1: (Field)) -> Field { assert_eq!(get_program_errors(src).len(), 1); } + #[test] fn deny_inline_attribute_on_unconstrained() { let src = r#" - #[inline(never)] + #[no_predicates] unconstrained fn foo(x: Field, y: Field) { assert(x != y); } @@ -1389,7 +1390,9 @@ fn lambda$f1(mut env$l1: (Field)) -> Field { assert_eq!(errors.len(), 1); assert!(matches!( errors[0].0, - CompilationError::ResolverError(ResolverError::InlineAttributeOnUnconstrained { .. }) + CompilationError::ResolverError( + ResolverError::NoPredicatesAttributeOnUnconstrained { .. } + ) )); } diff --git a/test_programs/execution_success/inline_never_basic/Nargo.toml b/test_programs/execution_success/no_predicates_basic/Nargo.toml similarity index 74% rename from test_programs/execution_success/inline_never_basic/Nargo.toml rename to test_programs/execution_success/no_predicates_basic/Nargo.toml index 16691770d76..bcefd550fb0 100644 --- a/test_programs/execution_success/inline_never_basic/Nargo.toml +++ b/test_programs/execution_success/no_predicates_basic/Nargo.toml @@ -1,5 +1,5 @@ [package] -name = "inline_never_basic" +name = "no_predicates_basic" type = "bin" authors = [""] compiler_version = ">=0.27.0" diff --git a/test_programs/execution_success/inline_never_basic/Prover.toml b/test_programs/execution_success/no_predicates_basic/Prover.toml similarity index 100% rename from test_programs/execution_success/inline_never_basic/Prover.toml rename to test_programs/execution_success/no_predicates_basic/Prover.toml diff --git a/test_programs/execution_success/inline_never_basic/src/main.nr b/test_programs/execution_success/no_predicates_basic/src/main.nr similarity index 87% rename from test_programs/execution_success/inline_never_basic/src/main.nr rename to test_programs/execution_success/no_predicates_basic/src/main.nr index 1922aaedb6c..d6037c2ab26 100644 --- a/test_programs/execution_success/inline_never_basic/src/main.nr +++ b/test_programs/execution_success/no_predicates_basic/src/main.nr @@ -2,7 +2,7 @@ fn main(x: Field, y: pub Field) { basic_check(x, y); } -#[inline(never)] +#[no_predicates] fn basic_check(x: Field, y: Field) { assert(x != y); } diff --git a/test_programs/execution_success/no_predicates_numeric_generic_poseidon/Nargo.toml b/test_programs/execution_success/no_predicates_numeric_generic_poseidon/Nargo.toml new file mode 100644 index 00000000000..1ce13c24287 --- /dev/null +++ b/test_programs/execution_success/no_predicates_numeric_generic_poseidon/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "no_predicates_numeric_generic_poseidon" +type = "bin" +authors = [""] +compiler_version = ">=0.28.0" + +[dependencies] \ No newline at end of file diff --git a/test_programs/execution_success/no_predicates_numeric_generic_poseidon/Prover.toml b/test_programs/execution_success/no_predicates_numeric_generic_poseidon/Prover.toml new file mode 100644 index 00000000000..00e821cf89d --- /dev/null +++ b/test_programs/execution_success/no_predicates_numeric_generic_poseidon/Prover.toml @@ -0,0 +1,2 @@ +enable = [true, false] +to_hash = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]] diff --git a/test_programs/execution_success/no_predicates_numeric_generic_poseidon/src/main.nr b/test_programs/execution_success/no_predicates_numeric_generic_poseidon/src/main.nr new file mode 100644 index 00000000000..dcb5e6bc5ca --- /dev/null +++ b/test_programs/execution_success/no_predicates_numeric_generic_poseidon/src/main.nr @@ -0,0 +1,33 @@ +use dep::std::hash::{pedersen_hash_with_separator, poseidon2::Poseidon2}; + +global NUM_HASHES = 2; +global HASH_LENGTH = 10; + +#[no_predicates] +pub fn poseidon_hash(inputs: [Field; N]) -> Field { + Poseidon2::hash(inputs, inputs.len()) +} + +fn main( + to_hash: [[Field; HASH_LENGTH]; NUM_HASHES], + enable: [bool; NUM_HASHES] +) -> pub [Field; NUM_HASHES + 1] { + let mut result = [0; NUM_HASHES + 1]; + for i in 0..NUM_HASHES { + let enable = enable[i]; + let to_hash = to_hash[i]; + if enable { + result[i] = poseidon_hash(to_hash); + } + } + + // We want to make sure that the function marked with `#[no_predicates]` with a numeric generic + // is monomorphized correctly. + let mut double_preimage = [0; 20]; + for i in 0..HASH_LENGTH * 2 { + double_preimage[i] = to_hash[0][i % HASH_LENGTH]; + } + result[NUM_HASHES] = poseidon_hash(double_preimage); + + result +} diff --git a/tooling/debugger/ignored-tests.txt b/tooling/debugger/ignored-tests.txt index 5e6ce18be54..f214be5e613 100644 --- a/tooling/debugger/ignored-tests.txt +++ b/tooling/debugger/ignored-tests.txt @@ -17,5 +17,6 @@ fold_basic_nested_call fold_call_witness_condition fold_after_inlined_calls fold_numeric_generic_poseidon -inline_never_basic +no_predicates_basic +no_predicates_numeric_generic_poseidon regression_4709