diff --git a/.noir-sync-commit b/.noir-sync-commit index d185957d716..803300f1653 100644 --- a/.noir-sync-commit +++ b/.noir-sync-commit @@ -1 +1 @@ -d8b9870a991b724ec337b58380b50464ba274d8a +6936a52bb4de2170b6e4c41afd9cf4327d4fbeb1 diff --git a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs index b6d837d9384..49525fc2ae1 100644 --- a/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs +++ b/noir/noir-repo/aztec_macros/src/transforms/note_interface.rs @@ -562,7 +562,9 @@ fn generate_note_properties_struct_source( .iter() .filter_map(|(field_name, _)| { if field_name != note_header_field_name { - Some(format!("{}: aztec::note::note_getter_options::PropertySelector", field_name)) + Some(format!( + "{field_name}: dep::aztec::note::note_getter_options::PropertySelector" + )) } else { None } @@ -667,7 +669,9 @@ fn generate_note_deserialize_content_source( ) } } else { - format!("{}: aztec::note::note_header::NoteHeader::empty()", note_header_field_name) + format!( + "{note_header_field_name}: dep::aztec::note::note_header::NoteHeader::empty()" + ) } }) .collect::>() diff --git a/noir/noir-repo/compiler/noirc_errors/src/reporter.rs b/noir/noir-repo/compiler/noirc_errors/src/reporter.rs index 42cab72345d..d817b48691f 100644 --- a/noir/noir-repo/compiler/noirc_errors/src/reporter.rs +++ b/noir/noir-repo/compiler/noirc_errors/src/reporter.rs @@ -1,3 +1,5 @@ +use std::io::IsTerminal; + use crate::{FileDiagnostic, Location, Span}; use codespan_reporting::diagnostic::{Diagnostic, Label}; use codespan_reporting::files::Files; @@ -148,7 +150,9 @@ pub fn report<'files>( call_stack: &[Location], deny_warnings: bool, ) -> bool { - let writer = StandardStream::stderr(ColorChoice::Always); + let color_choice = + if std::io::stderr().is_terminal() { ColorChoice::Auto } else { ColorChoice::Never }; + let writer = StandardStream::stderr(color_choice); let config = codespan_reporting::term::Config::default(); let stack_trace = stack_trace(files, call_stack); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs index f10ff834f6c..c2bc1e32cd6 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/brillig/brillig_gen/brillig_block.rs @@ -583,6 +583,11 @@ impl<'block> BrilligBlock<'block> { 1, ); } + + // `Intrinsic::AsWitness` is used to provide hints to acir-gen on optimal expression splitting. + // It is then useless in the brillig runtime and so we can ignore it + Value::Intrinsic(Intrinsic::AsWitness) => (), + _ => { unreachable!("unsupported function call type {:?}", dfg[*func]) } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/errors.rs b/noir/noir-repo/compiler/noirc_evaluator/src/errors.rs index dd63a254a18..0879056ad36 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/errors.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/errors.rs @@ -35,6 +35,12 @@ pub enum RuntimeError { UnknownLoopBound { call_stack: CallStack }, #[error("Argument is not constant")] AssertConstantFailed { call_stack: CallStack }, + #[error("The static_assert message is not constant")] + StaticAssertDynamicMessage { call_stack: CallStack }, + #[error("Argument is dynamic")] + StaticAssertDynamicPredicate { call_stack: CallStack }, + #[error("Argument is false")] + StaticAssertFailed { call_stack: CallStack }, #[error("Nested slices are not supported")] NestedSlice { call_stack: CallStack }, #[error("Big Integer modulus do no match")] @@ -120,6 +126,9 @@ impl RuntimeError { | RuntimeError::UnInitialized { call_stack, .. } | RuntimeError::UnknownLoopBound { call_stack } | RuntimeError::AssertConstantFailed { call_stack } + | RuntimeError::StaticAssertDynamicMessage { call_stack } + | RuntimeError::StaticAssertDynamicPredicate { call_stack } + | RuntimeError::StaticAssertFailed { call_stack } | RuntimeError::IntegerOutOfBounds { call_stack, .. } | RuntimeError::UnsupportedIntegerSize { call_stack, .. } | RuntimeError::NestedSlice { call_stack, .. } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs index 71fb51bf750..0e0c3f1e631 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa.rs @@ -66,7 +66,10 @@ pub(crate) fn optimize_into_acir( // Run mem2reg with the CFG separated into blocks .run_pass(Ssa::mem2reg, "After Mem2Reg:") .run_pass(Ssa::as_slice_optimization, "After `as_slice` optimization") - .try_run_pass(Ssa::evaluate_assert_constant, "After Assert Constant:")? + .try_run_pass( + Ssa::evaluate_static_assert_and_assert_constant, + "After `static_assert` and `assert_constant`:", + )? .try_run_pass(Ssa::unroll_loops_iteratively, "After Unrolling:")? .run_pass(Ssa::simplify_cfg, "After Simplifying:") .run_pass(Ssa::flatten_cfg, "After Flattening:") diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dfg.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dfg.rs index f763ae52d50..994386f8197 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dfg.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/dfg.rs @@ -497,9 +497,22 @@ impl DataFlowGraph { } } - /// True if the given ValueId refers to a constant value + /// True if the given ValueId refers to a (recursively) constant value pub(crate) fn is_constant(&self, argument: ValueId) -> bool { - !matches!(&self[self.resolve(argument)], Value::Instruction { .. } | Value::Param { .. }) + match &self[self.resolve(argument)] { + Value::Instruction { .. } | Value::Param { .. } => false, + Value::Array { array, .. } => array.iter().all(|element| self.is_constant(*element)), + _ => true, + } + } + + /// True that the input is a non-zero `Value::NumericConstant` + pub(crate) fn is_constant_true(&self, argument: ValueId) -> bool { + if let Some(constant) = self.get_numeric_constant(argument) { + !constant.is_zero() + } else { + false + } } } diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs index 8f881b86e47..f854e8e0693 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction.rs @@ -52,6 +52,7 @@ pub(crate) enum Intrinsic { ArrayLen, AsSlice, AssertConstant, + StaticAssert, SlicePushBack, SlicePushFront, SlicePopBack, @@ -76,6 +77,7 @@ impl std::fmt::Display for Intrinsic { Intrinsic::ArrayLen => write!(f, "array_len"), Intrinsic::AsSlice => write!(f, "as_slice"), Intrinsic::AssertConstant => write!(f, "assert_constant"), + Intrinsic::StaticAssert => write!(f, "static_assert"), Intrinsic::SlicePushBack => write!(f, "slice_push_back"), Intrinsic::SlicePushFront => write!(f, "slice_push_front"), Intrinsic::SlicePopBack => write!(f, "slice_pop_back"), @@ -104,9 +106,10 @@ impl Intrinsic { /// If there are no side effects then the `Intrinsic` can be removed if the result is unused. pub(crate) fn has_side_effects(&self) -> bool { match self { - Intrinsic::AssertConstant | Intrinsic::ApplyRangeConstraint | Intrinsic::AsWitness => { - true - } + Intrinsic::AssertConstant + | Intrinsic::StaticAssert + | Intrinsic::ApplyRangeConstraint + | Intrinsic::AsWitness => true, // These apply a constraint that the input must fit into a specified number of limbs. Intrinsic::ToBits(_) | Intrinsic::ToRadix(_) => true, @@ -142,6 +145,7 @@ impl Intrinsic { "array_len" => Some(Intrinsic::ArrayLen), "as_slice" => Some(Intrinsic::AsSlice), "assert_constant" => Some(Intrinsic::AssertConstant), + "static_assert" => Some(Intrinsic::StaticAssert), "apply_range_constraint" => Some(Intrinsic::ApplyRangeConstraint), "slice_push_back" => Some(Intrinsic::SlicePushBack), "slice_push_front" => Some(Intrinsic::SlicePushFront), diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs index e4635c0f974..281ab7c3057 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs @@ -246,6 +246,21 @@ pub(super) fn simplify_call( SimplifyResult::None } } + Intrinsic::StaticAssert => { + if arguments.len() != 2 { + panic!("ICE: static_assert called with wrong number of arguments") + } + + if !dfg.is_constant(arguments[1]) { + return SimplifyResult::None; + } + + if dfg.is_constant_true(arguments[0]) { + SimplifyResult::Remove + } else { + SimplifyResult::None + } + } Intrinsic::ApplyRangeConstraint => { let value = arguments[0]; let max_bit_size = dfg.get_numeric_constant(arguments[1]); diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/assert_constant.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/assert_constant.rs index a3608f89612..ae0681a55ff 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/assert_constant.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/assert_constant.rs @@ -22,7 +22,9 @@ impl Ssa { /// since we must go through every instruction to find all references to `assert_constant` /// while loop unrolling only touches blocks with loops in them. #[tracing::instrument(level = "trace", skip(self))] - pub(crate) fn evaluate_assert_constant(mut self) -> Result { + pub(crate) fn evaluate_static_assert_and_assert_constant( + mut self, + ) -> Result { for function in self.functions.values_mut() { for block in function.reachable_blocks() { // Unfortunately we can't just use instructions.retain(...) here since @@ -54,10 +56,13 @@ fn check_instruction( instruction: InstructionId, ) -> Result { let assert_constant_id = function.dfg.import_intrinsic(Intrinsic::AssertConstant); + let static_assert_id = function.dfg.import_intrinsic(Intrinsic::StaticAssert); match &function.dfg[instruction] { Instruction::Call { func, arguments } => { if *func == assert_constant_id { evaluate_assert_constant(function, instruction, arguments) + } else if *func == static_assert_id { + evaluate_static_assert(function, instruction, arguments) } else { Ok(true) } @@ -82,3 +87,35 @@ fn evaluate_assert_constant( Err(RuntimeError::AssertConstantFailed { call_stack }) } } + +/// Evaluate a call to `static_assert`, returning an error if the value is false +/// or not constant (see assert_constant). +/// +/// When it passes, Ok(false) is returned. This signifies a +/// success but also that the instruction need not be reinserted into the block being unrolled +/// since it has already been evaluated. +fn evaluate_static_assert( + function: &Function, + instruction: InstructionId, + arguments: &[ValueId], +) -> Result { + if arguments.len() != 2 { + panic!("ICE: static_assert called with wrong number of arguments") + } + + if !function.dfg.is_constant(arguments[1]) { + let call_stack = function.dfg.get_call_stack(instruction); + return Err(RuntimeError::StaticAssertDynamicMessage { call_stack }); + } + + if function.dfg.is_constant_true(arguments[0]) { + Ok(false) + } else { + let call_stack = function.dfg.get_call_stack(instruction); + if function.dfg.is_constant(arguments[0]) { + Err(RuntimeError::StaticAssertFailed { call_stack }) + } else { + Err(RuntimeError::StaticAssertDynamicPredicate { call_stack }) + } + } +} diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_enable_side_effects.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_enable_side_effects.rs index c9a6b7bf9c3..f9a3c9a55eb 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_enable_side_effects.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_enable_side_effects.rs @@ -150,6 +150,7 @@ impl Context { Intrinsic::ArrayLen | Intrinsic::AssertConstant + | Intrinsic::StaticAssert | Intrinsic::ApplyRangeConstraint | Intrinsic::StrAsBytes | Intrinsic::ToBits(_) diff --git a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_if_else.rs b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_if_else.rs index fd7a1a06fc8..242eea7d6f4 100644 --- a/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_if_else.rs +++ b/noir/noir-repo/compiler/noirc_evaluator/src/ssa/opt/remove_if_else.rs @@ -226,6 +226,7 @@ fn slice_capacity_change( // These cases don't affect slice capacities Intrinsic::AssertConstant + | Intrinsic::StaticAssert | Intrinsic::ApplyRangeConstraint | Intrinsic::ArrayLen | Intrinsic::StrAsBytes diff --git a/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs b/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs index ae973385182..87cc7990753 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/ast/expression.rs @@ -189,23 +189,6 @@ impl ExpressionKind { struct_type: None, })) } - - /// Returns true if the expression is a literal integer - pub fn is_integer(&self) -> bool { - self.as_integer().is_some() - } - - fn as_integer(&self) -> Option { - let literal = match self { - ExpressionKind::Literal(literal) => literal, - _ => return None, - }; - - match literal { - Literal::Integer(integer, _) => Some(*integer), - _ => None, - } - } } impl Recoverable for ExpressionKind { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs index b03c38b46cb..bf6de746791 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/errors.rs @@ -50,6 +50,8 @@ pub enum ResolverError { NoSuchNumericTypeVariable { path: crate::ast::Path }, #[error("Closures cannot capture mutable variables")] CapturedMutableVariable { span: Span }, + #[error("Test functions are not allowed to have any parameters")] + TestFunctionHasParameters { span: Span }, #[error("Only struct types can be used in constructor expressions")] NonStructUsedInConstructor { typ: Type, span: Span }, #[error("Only struct types can have generics")] @@ -259,6 +261,11 @@ impl<'a> From<&'a ResolverError> for Diagnostic { "Mutable variable".into(), *span, ), + ResolverError::TestFunctionHasParameters { span } => Diagnostic::simple_error( + "Test functions cannot have any parameters".into(), + "Try removing the parameters or moving the test into a wrapper function".into(), + *span, + ), ResolverError::NonStructUsedInConstructor { typ, span } => Diagnostic::simple_error( "Only struct types can be used in constructor expressions".into(), format!("{typ} has no fields to construct it with"), diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs index b97677d9431..f98343ba52f 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lexer/token.rs @@ -28,7 +28,9 @@ pub enum BorrowedToken<'input> { BlockComment(&'input str, Option), Quote(&'input Tokens), QuotedType(QuotedTypeId), + /// < Less, + /// <= LessEqual, /// > Greater, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs index b64f0dbe286..ebf0503963e 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -612,6 +612,7 @@ impl<'interner> Monomorphizer<'interner> { }) .transpose()? .map(Box::new); + Ok(ast::Expression::Constrain(Box::new(expr), location, assert_message)) } HirStatement::Assign(assign) => self.assign(assign), diff --git a/noir/noir-repo/docs/docs/noir/concepts/assert.md b/noir/noir-repo/docs/docs/noir/concepts/assert.md index bcff613a695..2132de42072 100644 --- a/noir/noir-repo/docs/docs/noir/concepts/assert.md +++ b/noir/noir-repo/docs/docs/noir/concepts/assert.md @@ -1,9 +1,9 @@ --- title: Assert Function description: - Learn about the assert function in Noir, which can be used to explicitly constrain the predicate or - comparison expression that follows to be true, and what happens if the expression is false at - runtime. + Learn about the `assert` and `static_assert` functions in Noir, which can be used to explicitly + constrain the predicate or comparison expression that follows to be true, and what happens if + the expression is false at runtime or compile-time, respectively. keywords: [Noir programming language, assert statement, predicate expression, comparison expression] sidebar_position: 4 --- @@ -43,3 +43,36 @@ let s = myStruct { myField: y }; assert(s.myField == x, s); ``` +There is also a special `static_assert` function that behaves like `assert`, +but that runs at compile-time. + +```rust +fn main(xs: [Field; 3]) { + let x = 2 + 2; + let y = 4; + static_assert(x == y, "expected 2 + 2 to equal 4"); + + // This passes since the length of `xs` is known at compile-time + static_assert(xs.len() == 3, "expected the input to have 3 elements"); +} +``` + +This function fails when passed a dynamic (run-time) argument: + +```rust +fn main(x : Field, y : Field) { + // this fails because `x` is not known at compile-time + static_assert(x == 2, "expected x to be known at compile-time and equal to 2"); + + let mut example_slice = &[]; + if y == 4 { + example_slice = example_slice.push_back(0); + } + + // This fails because the length of `example_slice` is not known at + // compile-time + let error_message = "expected an empty slice, known at compile-time"; + static_assert(example_slice.len() == 0, error_message); +} +``` + diff --git a/noir/noir-repo/examples/.gitignore b/noir/noir-repo/examples/.gitignore new file mode 100644 index 00000000000..c4fdcad6719 --- /dev/null +++ b/noir/noir-repo/examples/.gitignore @@ -0,0 +1,2 @@ +target +proofs \ No newline at end of file diff --git a/noir/noir-repo/examples/codegen_verifier/.gitignore b/noir/noir-repo/examples/codegen_verifier/.gitignore index c0d62c447d3..ae13a24752c 100644 --- a/noir/noir-repo/examples/codegen_verifier/.gitignore +++ b/noir/noir-repo/examples/codegen_verifier/.gitignore @@ -1,4 +1,3 @@ out cache -target src/contract.sol \ No newline at end of file diff --git a/noir/noir-repo/examples/prove_and_verify/proofs/proof b/noir/noir-repo/examples/prove_and_verify/proofs/proof deleted file mode 100644 index 01d5ad27686..00000000000 Binary files a/noir/noir-repo/examples/prove_and_verify/proofs/proof and /dev/null differ diff --git a/noir/noir-repo/examples/prove_and_verify/prove_and_verify.sh b/noir/noir-repo/examples/prove_and_verify/prove_and_verify.sh index 01ee6c70738..df3ec3ff97a 100755 --- a/noir/noir-repo/examples/prove_and_verify/prove_and_verify.sh +++ b/noir/noir-repo/examples/prove_and_verify/prove_and_verify.sh @@ -11,4 +11,4 @@ $BACKEND prove -b ./target/hello_world.json -w ./target/witness.gz # TODO: backend should automatically generate vk if necessary. $BACKEND write_vk -b ./target/hello_world.json -$BACKEND verify -v ./target/vk -p ./proofs/proof \ No newline at end of file +$BACKEND verify -k ./target/vk -p ./proofs/proof \ No newline at end of file diff --git a/noir/noir-repo/noir_stdlib/src/lib.nr b/noir/noir-repo/noir_stdlib/src/lib.nr index 1a756f441ba..65da7e6e9ab 100644 --- a/noir/noir-repo/noir_stdlib/src/lib.nr +++ b/noir/noir-repo/noir_stdlib/src/lib.nr @@ -48,6 +48,11 @@ pub fn verify_proof(verification_key: [Field], proof: [Field], public_inputs: // Useful for debugging for-loop bounds. #[builtin(assert_constant)] pub fn assert_constant(x: T) {} + +// Asserts that the given value is both true and known at compile-time +#[builtin(static_assert)] +pub fn static_assert(predicate: bool, message: str) {} + // from_field and as_field are private since they are not valid for every type. // `as` should be the default for users to cast between primitive types, and in the future // traits can be used to work with generic types. diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_array/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_array/Nargo.toml new file mode 100644 index 00000000000..6171770b62b --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_array/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_array" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_array/src/main.nr b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_array/src/main.nr new file mode 100644 index 00000000000..43da3ef0eaa --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_array/src/main.nr @@ -0,0 +1,5 @@ +fn main( + dynamic_one: Field, // == 1 +) { + assert_constant([dynamic_one]); +} diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_plus/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_plus/Nargo.toml new file mode 100644 index 00000000000..e5583e53126 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_plus/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_plus" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_plus/src/main.nr b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_plus/src/main.nr new file mode 100644 index 00000000000..f8a377092a2 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_plus/src/main.nr @@ -0,0 +1,5 @@ +fn main( + dynamic_one: Field, // == 1 +) { + assert_constant(dynamic_one + 1 == 3); +} diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_slice/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_slice/Nargo.toml new file mode 100644 index 00000000000..d1d068a79b8 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_slice/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_slice" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_slice/src/main.nr b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_slice/src/main.nr new file mode 100644 index 00000000000..f07002d7d4c --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_slice/src/main.nr @@ -0,0 +1,5 @@ +fn main( + dynamic_one: Field, // == 1 +) { + assert_constant(&[dynamic_one]); +} diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_array/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_array/Nargo.toml new file mode 100644 index 00000000000..18781f4d57d --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_array/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_struct_array" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_array/src/main.nr b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_array/src/main.nr new file mode 100644 index 00000000000..b9f4dceafc0 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_array/src/main.nr @@ -0,0 +1,12 @@ +struct Foo { + field: Field, + array: [Field; 3], + slice: [Field], +} + +fn main( + dynamic_one: Field, // == 1 +) { + let foo_dynamic_array = Foo { field: 0, array: [dynamic_one, 2, 3], slice: &[] }; + assert_constant(foo_dynamic_array); +} diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_field/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_field/Nargo.toml new file mode 100644 index 00000000000..173ea44101a --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_field/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_struct_field" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_field/src/main.nr b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_field/src/main.nr new file mode 100644 index 00000000000..e7986c93b6b --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_field/src/main.nr @@ -0,0 +1,12 @@ +struct Foo { + field: Field, + array: [Field; 3], + slice: [Field], +} + +fn main( + dynamic_one: Field, // == 1 +) { + let foo_dynamic = Foo { field: dynamic_one, array: [1, 2, 3], slice: &[] }; + assert_constant(foo_dynamic); +} diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_slice/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_slice/Nargo.toml new file mode 100644 index 00000000000..426f4826a0b --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_slice/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_struct_slice" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_slice/src/main.nr b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_slice/src/main.nr new file mode 100644 index 00000000000..c775b563928 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_struct_slice/src/main.nr @@ -0,0 +1,12 @@ +struct Foo { + field: Field, + array: [Field; 3], + slice: [Field], +} + +fn main( + dynamic_one: Field, // == 1 +) { + let foo_dynamic_slice = Foo { field: 0, array: [1, 2, 3], slice: &[dynamic_one] }; + assert_constant(foo_dynamic_slice); +} diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_tuple/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_tuple/Nargo.toml new file mode 100644 index 00000000000..de7b2031300 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_tuple/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_dynamic_tuple" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_tuple/src/main.nr b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_tuple/src/main.nr new file mode 100644 index 00000000000..579a5a0991f --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_dynamic_tuple/src/main.nr @@ -0,0 +1,5 @@ +fn main( + dynamic_one: Field, // == 1 +) { + assert_constant((dynamic_one, 2)); +} diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_false/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/assert_constant_false/Nargo.toml new file mode 100644 index 00000000000..cb8d59f4293 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_false/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant_false" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/assert_constant_false/src/main.nr b/noir/noir-repo/test_programs/compile_failure/assert_constant_false/src/main.nr new file mode 100644 index 00000000000..f4e98cfec37 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/assert_constant_false/src/main.nr @@ -0,0 +1,3 @@ +fn main() { + std::static_assert(false, ""); +} diff --git a/noir/noir-repo/test_programs/compile_failure/builtin_function_declaration/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/builtin_function_declaration/Nargo.toml index 3835292a6ba..80312a7aec1 100644 --- a/noir/noir-repo/test_programs/compile_failure/builtin_function_declaration/Nargo.toml +++ b/noir/noir-repo/test_programs/compile_failure/builtin_function_declaration/Nargo.toml @@ -2,6 +2,6 @@ name = "builtin_function_declaration" type = "bin" authors = [""] -compiler_version = ">=0.23.0" +compiler_version = ">=0.31.0" -[dependencies] +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/builtin_function_declaration/src/main.nr b/noir/noir-repo/test_programs/compile_failure/builtin_function_declaration/src/main.nr index ed376557371..473b5405691 100644 --- a/noir/noir-repo/test_programs/compile_failure/builtin_function_declaration/src/main.nr +++ b/noir/noir-repo/test_programs/compile_failure/builtin_function_declaration/src/main.nr @@ -7,4 +7,4 @@ fn to_le_bits(_x: Field, _bit_size: u32) -> [u1] {} fn main(x: Field) -> pub u1 { let bits = to_le_bits(x, 100); bits[0] -} +} \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/Nargo.toml index 2597f0c4653..8bdefbbbd21 100644 --- a/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/Nargo.toml +++ b/noir/noir-repo/test_programs/compile_failure/non_comptime_local_fn_call/Nargo.toml @@ -2,6 +2,6 @@ name = "non_comptime_local_fn_call" type = "bin" authors = [""] -compiler_version = ">=0.31.0" +compiler_version = ">=0.23.0" [dependencies] diff --git a/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_array_len/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_array_len/Nargo.toml new file mode 100644 index 00000000000..1c6c13ce225 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_array_len/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "static_assert_dynamic_array_len" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_array_len/src/main.nr b/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_array_len/src/main.nr new file mode 100644 index 00000000000..9e4665f8ad8 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_array_len/src/main.nr @@ -0,0 +1,5 @@ +fn main( + dynamic_one: Field, // == 1 +) { + std::static_assert([1, 2, dynamic_one].len() == 4, ""); +} diff --git a/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_slice/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_slice/Nargo.toml new file mode 100644 index 00000000000..45e39ae24a8 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_slice/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "static_assert_dynamic_slice" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_slice/src/main.nr b/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_slice/src/main.nr new file mode 100644 index 00000000000..6621b8a1fb3 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/static_assert_dynamic_slice/src/main.nr @@ -0,0 +1,15 @@ +fn main( + dynamic_one: Field, // == 1 + dynamic_two: Field, // == 2 +) { + // length unknown at compile time + let mut dynamic_built_slice_pair = &[]; + if dynamic_one == 1 { + dynamic_built_slice_pair = dynamic_built_slice_pair.push_back(dynamic_one); + } + if dynamic_two == 2 { + dynamic_built_slice_pair = dynamic_built_slice_pair.push_back(dynamic_two); + } + + std::static_assert(dynamic_built_slice_pair.len() == 3, ""); +} diff --git a/noir/noir-repo/test_programs/compile_failure/static_assert_plus/Nargo.toml b/noir/noir-repo/test_programs/compile_failure/static_assert_plus/Nargo.toml new file mode 100644 index 00000000000..fdb90c0dc1c --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/static_assert_plus/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "static_assert_plus" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_failure/static_assert_plus/src/main.nr b/noir/noir-repo/test_programs/compile_failure/static_assert_plus/src/main.nr new file mode 100644 index 00000000000..2241743ddb0 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_failure/static_assert_plus/src/main.nr @@ -0,0 +1,7 @@ +fn main() { + let x = 2; + let y = 3; + let xy = x + y; + + std::static_assert(xy == 6, "2 + 3 != 6"); +} diff --git a/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/src/main.nr b/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/src/main.nr index d658823d519..164512b03db 100644 --- a/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_contract/abi_attribute/src/main.nr @@ -1,7 +1,7 @@ contract Foo { #[abi(foo)] global foo: Field = 42; - + #[abi(bar)] struct Bar { inner: Field diff --git a/noir/noir-repo/test_programs/compile_success_empty/assert_constant/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/assert_constant/Nargo.toml new file mode 100644 index 00000000000..f18d4828fdf --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/assert_constant/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "assert_constant" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_success_empty/assert_constant/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/assert_constant/src/main.nr new file mode 100644 index 00000000000..6910a2d17b2 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/assert_constant/src/main.nr @@ -0,0 +1,59 @@ +use std::static_assert; + +global GLOBAL_ONE = 1; +global GLOBAL_TWO = 2; +global GLOBAL_THREE = GLOBAL_ONE + GLOBAL_TWO; + +// contents known at compile time +// length known at compile time +global GLOBAL_ARRAY_PAIR = [GLOBAL_ONE, GLOBAL_TWO]; +global GLOBAL_SLICE_PAIR = &[GLOBAL_ONE, GLOBAL_TWO]; + +struct Foo { + field: Field, + array: [Field; 3], + slice: [Field], +} + +fn main( + dynamic_one: Field, // == 1 + dynamic_two: Field // == 2 +) { + // contents unknown at compile time + // length known at compile time + let dynamic_array_pair = [dynamic_one, dynamic_two]; + let dynamic_slice_pair = &[dynamic_one, dynamic_two]; + + assert_constant(true); + assert_constant(false); + + assert_constant(2 == 2); + assert_constant(1 + 1 == 2); + + // assert_constant doesn't check for true + assert_constant(1 + 1 == 3); + + let local_one = 1; + let local_two = 2; + let local_three = local_one + local_two; + let local_array_pair = [local_one, local_two]; + let local_slice_pair = &[local_one, local_two]; + + assert_constant(local_one); + assert_constant(local_three); + assert_constant(local_array_pair); + assert_constant(local_slice_pair); + + assert_constant(GLOBAL_ONE); + assert_constant(GLOBAL_THREE); + assert_constant(GLOBAL_ARRAY_PAIR); + assert_constant(GLOBAL_SLICE_PAIR); + + assert_constant([1, 2, dynamic_one].len() == 4); + + static_assert(dynamic_array_pair.len() == 2, ""); + static_assert(dynamic_slice_pair.len() == 2, ""); + + let foo = Foo { field: 0, array: [1, 2, 3], slice: &[] }; + assert_constant(foo); +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/macros/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/macros/src/main.nr index 1b00a084c61..587c2c4c077 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/macros/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/macros/src/main.nr @@ -2,7 +2,9 @@ comptime fn my_macro(x: Field, y: Field) -> Quoted { // Current version of macros in Noir are not hygienic // so we can quote a and b here and expect them to resolve // to the a and b in main at the callsite of my_macro. - quote { $x + $y + a + b } + quote { + $x + $y + a + b + } } fn main() { diff --git a/noir/noir-repo/test_programs/compile_success_empty/numeric_generics_explicit/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/numeric_generics_explicit/Nargo.toml index bc3d43498db..980e5db588a 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/numeric_generics_explicit/Nargo.toml +++ b/noir/noir-repo/test_programs/compile_success_empty/numeric_generics_explicit/Nargo.toml @@ -2,6 +2,5 @@ name = "numeric_generics_explicit" type = "bin" authors = [""] -compiler_version = ">=0.30.0" -[dependencies] \ No newline at end of file +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_empty/static_assert/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/static_assert/Nargo.toml new file mode 100644 index 00000000000..5dabd7803e3 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/static_assert/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "static_assert" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] \ No newline at end of file diff --git a/noir/noir-repo/test_programs/compile_success_empty/static_assert/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/static_assert/src/main.nr new file mode 100644 index 00000000000..e61d9388ceb --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/static_assert/src/main.nr @@ -0,0 +1,46 @@ +use std::static_assert; + +global GLOBAL_ONE = 1; +global GLOBAL_TWO = 2; +global GLOBAL_THREE = GLOBAL_ONE + GLOBAL_TWO; + +// contents known at compile time +// length known at compile time +global GLOBAL_ARRAY_PAIR = [GLOBAL_ONE, GLOBAL_TWO]; +global GLOBAL_SLICE_PAIR = &[GLOBAL_ONE, GLOBAL_TWO]; + +struct Foo { + field: Field, + array: [Field; 3], + slice: [Field], +} + +fn main( + dynamic_one: Field, // == 1 + dynamic_two: Field // == 2 +) { + // contents unknown at compile time + // length known at compile time + let dynamic_array_pair = [dynamic_one, dynamic_two]; + let dynamic_slice_pair = &[dynamic_one, dynamic_two]; + + static_assert(true, ""); + + static_assert(1 + 1 == 2, ""); + + let x = 2; + let y = 3; + let xy = x + y; + static_assert(xy == 5, ""); + + static_assert(3 == GLOBAL_THREE, ""); + + static_assert(GLOBAL_ARRAY_PAIR.len() == 2, ""); + static_assert(GLOBAL_SLICE_PAIR.len() == 2, ""); + + static_assert(dynamic_array_pair.len() == 2, ""); + static_assert(dynamic_slice_pair.len() == 2, ""); + + assert_constant([1, 2, dynamic_one].len() == 4); + static_assert([1, 2, dynamic_one].len() == 3, ""); +} diff --git a/noir/noir-repo/test_programs/compile_success_empty/trait_generics/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/trait_generics/src/main.nr index 56ce7e8970c..15591f2f2ea 100644 --- a/noir/noir-repo/test_programs/compile_success_empty/trait_generics/src/main.nr +++ b/noir/noir-repo/test_programs/compile_success_empty/trait_generics/src/main.nr @@ -15,7 +15,7 @@ trait MyInto { fn into(self) -> T; } -impl MyInto<[U; N]> for [T; N] where T: MyInto { +impl MyInto<[U; N]> for [T; N] where T: MyInto { fn into(self) -> [U; N] { self.map(|x: T| x.into()) } diff --git a/noir/noir-repo/test_programs/execution_success/regression_5202/Nargo.toml b/noir/noir-repo/test_programs/execution_failure/regression_5202/Nargo.toml similarity index 55% rename from noir/noir-repo/test_programs/execution_success/regression_5202/Nargo.toml rename to noir/noir-repo/test_programs/execution_failure/regression_5202/Nargo.toml index da3da06a306..dcdc044836e 100644 --- a/noir/noir-repo/test_programs/execution_success/regression_5202/Nargo.toml +++ b/noir/noir-repo/test_programs/execution_failure/regression_5202/Nargo.toml @@ -2,7 +2,6 @@ name = "regression_5202" type = "bin" authors = [""] -compiler_version = ">=0.30.0" +compiler_version = ">=0.29.0" [dependencies] -fraction = { path = "fraction" } diff --git a/noir/noir-repo/test_programs/execution_failure/regression_5202/src/main.nr b/noir/noir-repo/test_programs/execution_failure/regression_5202/src/main.nr new file mode 100644 index 00000000000..45ffafca4c7 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_failure/regression_5202/src/main.nr @@ -0,0 +1,41 @@ +trait ToField { + fn to_field(self) -> Field; +} + +impl ToField for bool { fn to_field(self) -> Field { self as Field } } + +unconstrained fn get_unconstrained_option() -> Option { + Option::some(13) +} + +unconstrained fn should_i_assert() -> bool { + false +} + +fn get_magical_boolean() -> bool { + let option = get_unconstrained_option(); + + let pre_assert = option.is_some().to_field(); + + if should_i_assert() { + // Note that `should_i_assert` is unconstrained, so Noir should not be able to infer + // any behavior from the contents of this block. In this case it is actually false, so the + // assertion below is not even executed (if it did it'd fail since the values are not equal). + + assert_eq(option, Option::some(42)); /// <- this seems to be the trigger for the bug + } + + // In my testing, the `option` value exhibits weird behavior from this point on, as if it had been mutated + let post_assert = option.is_some().to_field(); + + // The following expression should be true, but I can get it to evaluate to false depending on how I call it + pre_assert == post_assert +} + +fn main() { + let magic = get_magical_boolean(); + + // One of these asserts should fail. Before #5202, they would both pass + assert_eq(magic, true); + assert_eq(magic, false); +} diff --git a/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/Nargo.toml b/noir/noir-repo/test_programs/execution_success/as_witness/Nargo.toml similarity index 55% rename from noir/noir-repo/test_programs/execution_success/regression_5202/fraction/Nargo.toml rename to noir/noir-repo/test_programs/execution_success/as_witness/Nargo.toml index 82e929d0bc7..18f3f99b5b5 100644 --- a/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/Nargo.toml +++ b/noir/noir-repo/test_programs/execution_success/as_witness/Nargo.toml @@ -1,6 +1,6 @@ [package] -name = "fraction" -type = "lib" +name = "as_witness" +type = "bin" authors = [""] [dependencies] diff --git a/noir/noir-repo/test_programs/execution_success/as_witness/Prover.toml b/noir/noir-repo/test_programs/execution_success/as_witness/Prover.toml new file mode 100644 index 00000000000..cd8a5b5e03c --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/as_witness/Prover.toml @@ -0,0 +1 @@ +a = 42 \ No newline at end of file diff --git a/noir/noir-repo/test_programs/execution_success/as_witness/src/main.nr b/noir/noir-repo/test_programs/execution_success/as_witness/src/main.nr new file mode 100644 index 00000000000..a24f4af7669 --- /dev/null +++ b/noir/noir-repo/test_programs/execution_success/as_witness/src/main.nr @@ -0,0 +1,5 @@ +// Simple example of checking where two arrays are different +fn main(a: Field) -> pub Field { + std::as_witness(a); + a +} diff --git a/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/LICENSE b/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/LICENSE deleted file mode 100644 index 929af4807ca..00000000000 --- a/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2023 Resurgence Labs - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/README.md b/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/README.md deleted file mode 100644 index 17c81e5555a..00000000000 --- a/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# fraction -The Noir repository for accessing Fractions by Resurgence Labs - -# usage -To Use as a Dependency, add the following line to your project's Nargo.toml under [dependencies]: -fraction = { tag = "v1.2.2", git = "https://github.com/resurgencelabs/fraction" } - -Note: This is a highly dynamic repository. The code will change as more features are added, both at the repository level by Resurgence Labs, as well as at the language level itself by the Noir team. - - diff --git a/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/src/lib.nr b/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/src/lib.nr deleted file mode 100644 index 4b20eb6b76c..00000000000 --- a/noir/noir-repo/test_programs/execution_success/regression_5202/fraction/src/lib.nr +++ /dev/null @@ -1,201 +0,0 @@ -use dep::std; - -global MAX: Fraction = Fraction { sign: true, num: 3050913689, den: 1 }; -global MIN: Fraction = Fraction { sign: false, num: 3050913689, den: 1 }; -global ZERO: Fraction = Fraction { sign: true, num: 0, den: 1 }; -global ONE: Fraction = Fraction { sign: true, num: 1, den: 1 }; -global NEGATIVE_ONE: Fraction = Fraction { sign: false, num: 1, den: 1 }; - -struct Fraction { - sign: bool, - num: u32, - den: u32, -} - -// Create a Fraction type variable without lenghtier code -pub fn toFraction(s: bool, n: u32, d: u32) -> Fraction { - assert(d != 0); - Fraction { sign: s, num: n, den: d } -} - -// Swaps the numerator and denominator -fn invertFraction(f: Fraction) -> Fraction { - assert(f.num != 0); - Fraction { sign: f.sign, num: f.den, den: f.num } -} - -// Changes the Sign of the Fraction -fn signChangeFraction(f: Fraction) -> Fraction { - Fraction { sign: !f.sign, num: f.num, den: f.den } -} - -// this method will only work till numerator and denominator values are under 100 -// this has been set for efficiency reasons, and will be modified once the Noir team -// can implement dynamic limit for loops -fn reduceFraction(f: Fraction) -> Fraction { - let mut a = f.num; - let mut b = f.den; - let mut j = 1; - let mut gcd = 1; - - let min = if a > b { b } else { a }; - - for i in 2..100 { - j = i as u32; - if (j <= min) { - if (a % j == 0) & (b % j == 0) { - gcd = j; - } - } - } - - Fraction { sign: f.sign, num: f.num / gcd, den: f.den / gcd } -} - -// Adds two fractions -pub fn addFraction(f1: Fraction, f2: Fraction) -> Fraction { - let mut an = U128::from_integer(f1.num); - let mut ad = U128::from_integer(f1.den); - let mut bn = U128::from_integer(f2.num); - let mut bd = U128::from_integer(f2.den); - let mut m = f1; - let mut n = f2; - - if f1.sign == f2.sign { - if ((ad * bd > U128::from_integer(2000000000)) - | ((an * bd + ad * bn) > U128::from_integer(2000000000)) - | ((an * bd) > U128::from_integer(2000000000)) - | ((ad * bn) > U128::from_integer(2000000000))) { - m = reduceFraction(m); - n = reduceFraction(n); - } - an = U128::from_integer(m.num); - ad = U128::from_integer(m.den); - bn = U128::from_integer(n.num); - bd = U128::from_integer(n.den); - if ((ad * bd > U128::from_integer(2000000000)) - | ((an * bd + ad * bn) > U128::from_integer(2000000000)) - | ((an * bd) > U128::from_integer(2000000000)) - | ((ad * bn) > U128::from_integer(2000000000))) { - let mut ddd = (an * bd + ad * bn) / (ad * bd); - let mut factor = U128::from_integer(1); - for _ in 1..5 { - if ddd * U128::from_integer(10) < U128::from_integer(2000000000) { - ddd *= U128::from_integer(10); - factor *= U128::from_integer(10); - } - } - let np: u32 = U128::to_integer(((an * bd + ad * bn) * factor) / (ad * bd)); - let fx: u32 = U128::to_integer(factor); - Fraction { sign: f1.sign, num: np, den: fx } - } else { - Fraction { sign: f1.sign, num: (m.num * n.den + n.num * m.den), den: m.den * n.den } - } - } else if ((an * bd) > (bn * ad)) { - if ((ad * bd > U128::from_integer(2000000000)) - | ((an * bd - ad * bn) > U128::from_integer(2000000000)) - | ((an * bd) > U128::from_integer(2000000000))) { - m = reduceFraction(m); - n = reduceFraction(n); - } - an = U128::from_integer(m.num); - ad = U128::from_integer(m.den); - bn = U128::from_integer(n.num); - bd = U128::from_integer(n.den); - - if ((ad * bd > U128::from_integer(2000000000)) - | ((an * bd - ad * bn) > U128::from_integer(2000000000)) - | ((an * bd) > U128::from_integer(2000000000))) { - let mut ddd = (an * bd - ad * bn) / (ad * bd); - let mut factor = U128::from_integer(1); - for _ in 1..5 { - if ddd * U128::from_integer(10) < U128::from_integer(2000000000) { - ddd *= U128::from_integer(10); - factor *= U128::from_integer(10); - } - } - let np: u32 = U128::to_integer(((an * bd - ad * bn) * factor) / (ad * bd)); - let fx: u32 = U128::to_integer(factor); - Fraction { sign: f1.sign, num: np, den: fx } - } else { - Fraction { sign: f1.sign, num: (m.num * n.den - n.num * m.den), den: m.den * n.den } - } - } else { - if ((ad * bd > U128::from_integer(2000000000)) - | ((bn * ad - bd * an) > U128::from_integer(2000000000)) - | ((bn * ad) > U128::from_integer(2000000000))) { - m = reduceFraction(m); - n = reduceFraction(n); - } - an = U128::from_integer(m.num); - ad = U128::from_integer(m.den); - bn = U128::from_integer(n.num); - bd = U128::from_integer(n.den); - if ((ad * bd > U128::from_integer(2000000000)) - | ((bn * ad - bd * an) > U128::from_integer(2000000000)) - | ((bn * ad) > U128::from_integer(2000000000))) { - let mut ddd = (bn * ad - bd * an) / (ad * bd); - let mut factor = U128::from_integer(1); - for _ in 1..5 { - if ddd * U128::from_integer(10) < U128::from_integer(2000000000) { - ddd *= U128::from_integer(10); - factor *= U128::from_integer(10); - } - } - let np: u32 = U128::to_integer(((bn * ad - bd * an) * factor) / (ad * bd)); - let fx: u32 = U128::to_integer(factor); - Fraction { sign: f2.sign, num: np, den: fx } - } else { - Fraction { sign: f2.sign, num: (n.num * m.den - m.num * n.den), den: m.den * n.den } - } - } -} - -// Returns the closest but smaller Integer to the Given Fraction, but typecast to Fraction for convenience -pub fn floor(f: Fraction) -> Fraction { - let q = f.num / f.den; - if q * f.den == f.num { - Fraction { sign: f.sign, num: f.num, den: f.den } - } else if f.sign { - Fraction { sign: f.sign, num: q, den: 1 } - } else { - Fraction { sign: f.sign, num: q + 1, den: 1 } - } -} - -#[test] -fn test_sum() { - let f1 = toFraction(true, 3, 5); - let f2 = toFraction(true, 2, 5); - let f = addFraction(f1, f2); - assert(f.num == f.den); -} - -#[test] -fn test_reduce() { - let f1 = toFraction(true, 2, 10); - let f2 = reduceFraction(f1); - assert(f2.num == 1); -} - -#[test] -fn test_floor() { - let f = toFraction(true, 7, 5); - let fl = floor(f); - assert(fl.num == 1); - assert(fl.den == 1); -} - -#[test] -fn test_floor2() { - let f = toFraction(false, 12, 5); - let fl = floor(f); - assert(fl.num == 3); - assert(fl.den == 1); -} - -#[test] -fn test_globals() { - let a = addFraction(ONE, NEGATIVE_ONE); - assert(a.num == ZERO.num); -} diff --git a/noir/noir-repo/test_programs/execution_success/regression_5202/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_5202/src/main.nr deleted file mode 100644 index 2ebfd7890ba..00000000000 --- a/noir/noir-repo/test_programs/execution_success/regression_5202/src/main.nr +++ /dev/null @@ -1,23 +0,0 @@ -use fraction::{Fraction, MAX, floor, toFraction, addFraction}; - -fn main() { - let g1 = toFraction(true, 33333333, 5); - let g2 = toFraction(true, 500000, 33333333); - let a = addFraction(g1, g2); - - let f1 = floor(a); - let f2 = MAX; - assert(f1.sign); - assert(f2.sign); - - if f1.sign != f2.sign { - if (f1.sign) { () } else { () } - } else { - // Test fails here before the fix to #5202. - // An optimization which assumes an if condition to be true/false - // within the then/else branch respectively wasn't being set properly - // causing f1.sign to be assumed to be false in this else branch. - assert(f1.sign); - assert(f2.sign); - } -}