From 94464026b3953a6f3a171a98346a2cf2f3ed3c37 Mon Sep 17 00:00:00 2001 From: Jake Fecher Date: Tue, 30 Jul 2024 13:16:47 -0500 Subject: [PATCH] Add --arithmetic-generics flag --- aztec_macros/src/utils/hir_utils.rs | 4 ++-- compiler/noirc_driver/src/lib.rs | 22 +++++++++---------- .../noirc_frontend/src/elaborator/comptime.rs | 1 + compiler/noirc_frontend/src/elaborator/mod.rs | 13 +++++++++-- .../noirc_frontend/src/elaborator/types.rs | 11 +++++++++- .../noirc_frontend/src/hir/comptime/tests.rs | 2 +- .../src/hir/def_collector/dc_crate.rs | 5 ++++- .../noirc_frontend/src/hir/def_map/mod.rs | 2 ++ .../src/hir/resolution/errors.rs | 9 ++++++++ compiler/noirc_frontend/src/hir_def/types.rs | 2 +- compiler/noirc_frontend/src/tests.rs | 5 +++-- tooling/lsp/src/notifications/mod.rs | 2 +- tooling/lsp/src/requests/code_lens_request.rs | 2 +- tooling/lsp/src/requests/mod.rs | 2 +- tooling/lsp/src/requests/test_run.rs | 2 +- tooling/lsp/src/requests/tests.rs | 2 +- tooling/nargo_cli/build.rs | 2 +- tooling/nargo_cli/src/cli/check_cmd.rs | 14 ++++-------- tooling/nargo_cli/src/cli/export_cmd.rs | 5 +---- tooling/nargo_cli/src/cli/test_cmd.rs | 9 ++------ 20 files changed, 67 insertions(+), 49 deletions(-) diff --git a/aztec_macros/src/utils/hir_utils.rs b/aztec_macros/src/utils/hir_utils.rs index 200ce3099cb..0a8ce371708 100644 --- a/aztec_macros/src/utils/hir_utils.rs +++ b/aztec_macros/src/utils/hir_utils.rs @@ -195,7 +195,7 @@ pub fn inject_fn( let trait_id = None; items.functions.push(UnresolvedFunctions { file_id, functions, trait_id, self_type: None }); - let mut errors = Elaborator::elaborate(context, *crate_id, items, None); + let mut errors = Elaborator::elaborate(context, *crate_id, items, None, false); errors.retain(|(error, _)| !CustomDiagnostic::from(error).is_warning()); if !errors.is_empty() { @@ -241,7 +241,7 @@ pub fn inject_global( let mut items = CollectedItems::default(); items.globals.push(UnresolvedGlobal { file_id, module_id, global_id, stmt_def: global }); - let _errors = Elaborator::elaborate(context, *crate_id, items, None); + let _errors = Elaborator::elaborate(context, *crate_id, items, None, false); } pub fn fully_qualified_note_path(context: &HirContext, note_id: StructId) -> Option { diff --git a/compiler/noirc_driver/src/lib.rs b/compiler/noirc_driver/src/lib.rs index f430eb8ad19..20ab1fb97f8 100644 --- a/compiler/noirc_driver/src/lib.rs +++ b/compiler/noirc_driver/src/lib.rs @@ -113,6 +113,10 @@ pub struct CompileOptions { /// Outputs the paths to any modified artifacts #[arg(long, hide = true)] pub show_artifact_paths: bool, + + /// Outputs the paths to any modified artifacts + #[arg(long, hide = true)] + pub arithmetic_generics: bool, } pub fn parse_expression_width(input: &str) -> Result { @@ -262,21 +266,19 @@ pub fn add_dep( pub fn check_crate( context: &mut Context, crate_id: CrateId, - deny_warnings: bool, - disable_macros: bool, - debug_comptime_in_file: Option<&str>, + options: &CompileOptions, ) -> CompilationResult<()> { let macros: &[&dyn MacroProcessor] = - if disable_macros { &[] } else { &[&aztec_macros::AztecMacro as &dyn MacroProcessor] }; + if options.disable_macros { &[] } else { &[&aztec_macros::AztecMacro as &dyn MacroProcessor] }; let mut errors = vec![]; - let diagnostics = CrateDefMap::collect_defs(crate_id, context, debug_comptime_in_file, macros); + let diagnostics = CrateDefMap::collect_defs(crate_id, context, options.debug_comptime_in_file.as_deref(), options.arithmetic_generics, macros); errors.extend(diagnostics.into_iter().map(|(error, file_id)| { let diagnostic = CustomDiagnostic::from(&error); diagnostic.in_file(file_id) })); - if has_errors(&errors, deny_warnings) { + if has_errors(&errors, options.deny_warnings) { Err(errors) } else { Ok(((), errors)) @@ -305,9 +307,7 @@ pub fn compile_main( let (_, mut warnings) = check_crate( context, crate_id, - options.deny_warnings, - options.disable_macros, - options.debug_comptime_in_file.as_deref(), + options, )?; let main = context.get_main_function(&crate_id).ok_or_else(|| { @@ -346,9 +346,7 @@ pub fn compile_contract( let (_, warnings) = check_crate( context, crate_id, - options.deny_warnings, - options.disable_macros, - options.debug_comptime_in_file.as_deref(), + options, )?; // TODO: We probably want to error if contracts is empty diff --git a/compiler/noirc_frontend/src/elaborator/comptime.rs b/compiler/noirc_frontend/src/elaborator/comptime.rs index 402ff31dafe..e274c12b3b2 100644 --- a/compiler/noirc_frontend/src/elaborator/comptime.rs +++ b/compiler/noirc_frontend/src/elaborator/comptime.rs @@ -21,6 +21,7 @@ impl<'context> Elaborator<'context> { self.def_maps, self.crate_id, self.debug_comptime_in_file, + self.enable_arithmetic_generics, ); elaborator.function_context.push(FunctionContext::default()); diff --git a/compiler/noirc_frontend/src/elaborator/mod.rs b/compiler/noirc_frontend/src/elaborator/mod.rs index 84572a7b413..4691eacdc42 100644 --- a/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/compiler/noirc_frontend/src/elaborator/mod.rs @@ -176,6 +176,9 @@ pub struct Elaborator<'context> { /// This map is used to lazily evaluate these globals if they're encountered before /// they are elaborated (e.g. in a function's type or another global's RHS). unresolved_globals: BTreeMap, + + /// Temporary flag to enable the experimental arithmetic generics feature + enable_arithmetic_generics: bool, } #[derive(Default)] @@ -198,6 +201,7 @@ impl<'context> Elaborator<'context> { def_maps: &'context mut DefMaps, crate_id: CrateId, debug_comptime_in_file: Option, + enable_arithmetic_generics: bool, ) -> Self { Self { scopes: ScopeForest::default(), @@ -219,6 +223,7 @@ impl<'context> Elaborator<'context> { comptime_scopes: vec![HashMap::default()], debug_comptime_in_file, unresolved_globals: BTreeMap::new(), + enable_arithmetic_generics, } } @@ -226,12 +231,14 @@ impl<'context> Elaborator<'context> { context: &'context mut Context, crate_id: CrateId, debug_comptime_in_file: Option, + enable_arithmetic_generics: bool, ) -> Self { Self::new( &mut context.def_interner, &mut context.def_maps, crate_id, debug_comptime_in_file, + enable_arithmetic_generics, ) } @@ -240,8 +247,9 @@ impl<'context> Elaborator<'context> { crate_id: CrateId, items: CollectedItems, debug_comptime_in_file: Option, + enable_arithmetic_generics: bool, ) -> Vec<(CompilationError, FileId)> { - Self::elaborate_and_return_self(context, crate_id, items, debug_comptime_in_file).errors + Self::elaborate_and_return_self(context, crate_id, items, debug_comptime_in_file, enable_arithmetic_generics).errors } pub fn elaborate_and_return_self( @@ -249,8 +257,9 @@ impl<'context> Elaborator<'context> { crate_id: CrateId, items: CollectedItems, debug_comptime_in_file: Option, + enable_arithmetic_generics: bool, ) -> Self { - let mut this = Self::from_context(context, crate_id, debug_comptime_in_file); + let mut this = Self::from_context(context, crate_id, debug_comptime_in_file, enable_arithmetic_generics); this.elaborate_items(items); this.check_and_pop_function_context(); this diff --git a/compiler/noirc_frontend/src/elaborator/types.rs b/compiler/noirc_frontend/src/elaborator/types.rs index 590094166be..e148c65ac9c 100644 --- a/compiler/noirc_frontend/src/elaborator/types.rs +++ b/compiler/noirc_frontend/src/elaborator/types.rs @@ -385,6 +385,7 @@ impl<'context> Elaborator<'context> { } UnresolvedTypeExpression::Constant(int, _) => Type::Constant(int), UnresolvedTypeExpression::BinaryOperation(lhs, op, rhs, _) => { + let (lhs_span, rhs_span) = (lhs.span(), rhs.span()); let lhs = self.convert_expression_type(*lhs); let rhs = self.convert_expression_type(*rhs); @@ -392,7 +393,15 @@ impl<'context> Elaborator<'context> { (Type::Constant(lhs), Type::Constant(rhs)) => { Type::Constant(op.function(lhs, rhs)) } - (lhs, rhs) => Type::InfixExpr(Box::new(lhs), op, Box::new(rhs)), + (lhs, rhs) => { + if !self.enable_arithmetic_generics { + let span = + if !matches!(lhs, Type::Constant(_)) { lhs_span } else { rhs_span }; + self.push_err(ResolverError::InvalidArrayLengthExpr { span }); + } + + Type::InfixExpr(Box::new(lhs), op, Box::new(rhs)).canonicalize() + } } } } diff --git a/compiler/noirc_frontend/src/hir/comptime/tests.rs b/compiler/noirc_frontend/src/hir/comptime/tests.rs index b4ffa1bd01d..4c1adf9fca0 100644 --- a/compiler/noirc_frontend/src/hir/comptime/tests.rs +++ b/compiler/noirc_frontend/src/hir/comptime/tests.rs @@ -45,7 +45,7 @@ fn interpret_helper(src: &str) -> Result { let main = context.get_main_function(&krate).expect("Expected 'main' function"); let mut elaborator = - Elaborator::elaborate_and_return_self(&mut context, krate, collector.items, None); + Elaborator::elaborate_and_return_self(&mut context, krate, collector.items, None, false); assert_eq!(elaborator.errors.len(), 0); let mut interpreter = elaborator.setup_interpreter(); diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 60489660762..ed3b98f0a1a 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -247,6 +247,7 @@ impl DefCollector { ast: SortedModule, root_file_id: FileId, debug_comptime_in_file: Option<&str>, + enable_arithmetic_generics: bool, macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { let mut errors: Vec<(CompilationError, FileId)> = vec![]; @@ -264,6 +265,7 @@ impl DefCollector { dep.crate_id, context, debug_comptime_in_file, + enable_arithmetic_generics, macro_processors, )); @@ -387,7 +389,8 @@ impl DefCollector { }); let mut more_errors = - Elaborator::elaborate(context, crate_id, def_collector.items, debug_comptime_in_file); + Elaborator::elaborate(context, crate_id, def_collector.items, debug_comptime_in_file, enable_arithmetic_generics); + errors.append(&mut more_errors); for macro_processor in macro_processors { diff --git a/compiler/noirc_frontend/src/hir/def_map/mod.rs b/compiler/noirc_frontend/src/hir/def_map/mod.rs index 45f1f17940d..e607de52ff1 100644 --- a/compiler/noirc_frontend/src/hir/def_map/mod.rs +++ b/compiler/noirc_frontend/src/hir/def_map/mod.rs @@ -76,6 +76,7 @@ impl CrateDefMap { crate_id: CrateId, context: &mut Context, debug_comptime_in_file: Option<&str>, + enable_arithmetic_generics: bool, macro_processors: &[&dyn MacroProcessor], ) -> Vec<(CompilationError, FileId)> { // Check if this Crate has already been compiled @@ -125,6 +126,7 @@ impl CrateDefMap { ast, root_file_id, debug_comptime_in_file, + enable_arithmetic_generics, macro_processors, )); diff --git a/compiler/noirc_frontend/src/hir/resolution/errors.rs b/compiler/noirc_frontend/src/hir/resolution/errors.rs index bf6de746791..c573698184f 100644 --- a/compiler/noirc_frontend/src/hir/resolution/errors.rs +++ b/compiler/noirc_frontend/src/hir/resolution/errors.rs @@ -116,6 +116,8 @@ pub enum ResolverError { NonFunctionInAnnotation { span: Span }, #[error("Unknown annotation")] UnknownAnnotation { span: Span }, + #[error("Arithmetic Generics are currently experimental")] + ArithmeticGenerics { span: Span }, } impl ResolverError { @@ -467,6 +469,13 @@ impl<'a> From<&'a ResolverError> for Diagnostic { *span, ) }, + ResolverError::ArithmeticGenerics { span } => { + Diagnostic::simple_warning( + "Arithmetic Generics are currently an experimental feature".into(), + "Use --arithmetic-generics to enable this feature".into(), + *span, + ) + }, } } } diff --git a/compiler/noirc_frontend/src/hir_def/types.rs b/compiler/noirc_frontend/src/hir_def/types.rs index d01cfb917b0..f5e43a2a5db 100644 --- a/compiler/noirc_frontend/src/hir_def/types.rs +++ b/compiler/noirc_frontend/src/hir_def/types.rs @@ -1627,7 +1627,7 @@ impl Type { /// For example: /// - `canonicalize[((1 + N) + M) + 2] = (M + N) + 3` /// - `canonicalize[A + 2 * B + 3 - 2] = A + (B * 2) + 3 - 2` - fn canonicalize(&self) -> Type { + pub fn canonicalize(&self) -> Type { match self.follow_bindings() { Type::InfixExpr(lhs, op, rhs) => { if let Some(value) = self.evaluate_to_u32() { diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index f2b83a48022..65fdaae81c4 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -82,8 +82,9 @@ pub(crate) fn get_program(src: &str) -> (ParsedModule, Context, Vec<(Compilation &mut context, program.clone().into_sorted(), root_file_id, - None, // No debug_comptime_in_file - &[], // No macro processors + None, // No debug_comptime_in_file + false, // Disallow arithmetic generics + &[], // No macro processors )); } (program, context, errors) diff --git a/tooling/lsp/src/notifications/mod.rs b/tooling/lsp/src/notifications/mod.rs index 24409e85db8..ad658eefcf0 100644 --- a/tooling/lsp/src/notifications/mod.rs +++ b/tooling/lsp/src/notifications/mod.rs @@ -162,7 +162,7 @@ pub(crate) fn process_workspace_for_noir_document( let (mut context, crate_id) = crate::prepare_package(&workspace_file_manager, &parsed_files, package); - let file_diagnostics = match check_crate(&mut context, crate_id, false, false, None) { + let file_diagnostics = match check_crate(&mut context, crate_id, &Default::default()) { Ok(((), warnings)) => warnings, Err(errors_and_warnings) => errors_and_warnings, }; diff --git a/tooling/lsp/src/requests/code_lens_request.rs b/tooling/lsp/src/requests/code_lens_request.rs index 51336a324da..17edf5e11c5 100644 --- a/tooling/lsp/src/requests/code_lens_request.rs +++ b/tooling/lsp/src/requests/code_lens_request.rs @@ -73,7 +73,7 @@ fn on_code_lens_request_inner( let (mut context, crate_id) = prepare_source(source_string, state); // We ignore the warnings and errors produced by compilation for producing code lenses // because we can still get the test functions even if compilation fails - let _ = check_crate(&mut context, crate_id, false, false, None); + let _ = check_crate(&mut context, crate_id, &Default::default()); let collected_lenses = collect_lenses_for_package(&context, crate_id, &workspace, package, None); diff --git a/tooling/lsp/src/requests/mod.rs b/tooling/lsp/src/requests/mod.rs index 4d261c1b50a..067cc22be63 100644 --- a/tooling/lsp/src/requests/mod.rs +++ b/tooling/lsp/src/requests/mod.rs @@ -382,7 +382,7 @@ where interner = def_interner; } else { // We ignore the warnings and errors produced by compilation while resolving the definition - let _ = noirc_driver::check_crate(&mut context, crate_id, false, false, None); + let _ = noirc_driver::check_crate(&mut context, crate_id, &Default::default()); interner = &context.def_interner; } diff --git a/tooling/lsp/src/requests/test_run.rs b/tooling/lsp/src/requests/test_run.rs index bf4d9763faf..fc4054633e2 100644 --- a/tooling/lsp/src/requests/test_run.rs +++ b/tooling/lsp/src/requests/test_run.rs @@ -61,7 +61,7 @@ fn on_test_run_request_inner( Some(package) => { let (mut context, crate_id) = crate::prepare_package(&workspace_file_manager, &parsed_files, package); - if check_crate(&mut context, crate_id, false, false, None).is_err() { + if check_crate(&mut context, crate_id, &Default::default()).is_err() { let result = NargoTestRunResult { id: params.id.clone(), result: "error".to_string(), diff --git a/tooling/lsp/src/requests/tests.rs b/tooling/lsp/src/requests/tests.rs index 20b96029696..7203aca7f09 100644 --- a/tooling/lsp/src/requests/tests.rs +++ b/tooling/lsp/src/requests/tests.rs @@ -65,7 +65,7 @@ fn on_tests_request_inner( crate::prepare_package(&workspace_file_manager, &parsed_files, package); // We ignore the warnings and errors produced by compilation for producing tests // because we can still get the test functions even if compilation fails - let _ = check_crate(&mut context, crate_id, false, false, None); + let _ = check_crate(&mut context, crate_id, &Default::default()); // We don't add test headings for a package if it contains no `#[test]` functions get_package_tests_in_crate(&context, &crate_id, &package.name) diff --git a/tooling/nargo_cli/build.rs b/tooling/nargo_cli/build.rs index 74e07efb5c1..3f8cd055569 100644 --- a/tooling/nargo_cli/build.rs +++ b/tooling/nargo_cli/build.rs @@ -218,7 +218,7 @@ fn generate_compile_success_empty_tests(test_file: &mut File, test_data_dir: &Pa &test_dir, &format!( r#" - nargo.arg("info").arg("--json").arg("--force"); + nargo.arg("info").arg("--arithmetic-generics").arg("--json").arg("--force"); {assert_zero_opcodes}"#, ), diff --git a/tooling/nargo_cli/src/cli/check_cmd.rs b/tooling/nargo_cli/src/cli/check_cmd.rs index d40bae1ecfd..eb5c7b897bb 100644 --- a/tooling/nargo_cli/src/cli/check_cmd.rs +++ b/tooling/nargo_cli/src/cli/check_cmd.rs @@ -84,10 +84,7 @@ fn check_package( check_crate_and_report_errors( &mut context, crate_id, - compile_options.deny_warnings, - compile_options.disable_macros, - compile_options.silence_warnings, - compile_options.debug_comptime_in_file.as_deref(), + compile_options, )?; if package.is_library() || package.is_contract() { @@ -157,14 +154,11 @@ fn create_input_toml_template( pub(crate) fn check_crate_and_report_errors( context: &mut Context, crate_id: CrateId, - deny_warnings: bool, - disable_macros: bool, - silence_warnings: bool, - debug_comptime_in_file: Option<&str>, + options: &CompileOptions, ) -> Result<(), CompileError> { let result = - check_crate(context, crate_id, deny_warnings, disable_macros, debug_comptime_in_file); - report_errors(result, &context.file_manager, deny_warnings, silence_warnings) + check_crate(context, crate_id, options); + report_errors(result, &context.file_manager, options.deny_warnings, options.silence_warnings) } #[cfg(test)] diff --git a/tooling/nargo_cli/src/cli/export_cmd.rs b/tooling/nargo_cli/src/cli/export_cmd.rs index 1b7ba97d68d..3c4c5be2e05 100644 --- a/tooling/nargo_cli/src/cli/export_cmd.rs +++ b/tooling/nargo_cli/src/cli/export_cmd.rs @@ -86,10 +86,7 @@ fn compile_exported_functions( check_crate_and_report_errors( &mut context, crate_id, - compile_options.deny_warnings, - compile_options.disable_macros, - compile_options.silence_warnings, - compile_options.debug_comptime_in_file.as_deref(), + compile_options, )?; let exported_functions = context.get_all_exported_functions_in_crate(&crate_id); diff --git a/tooling/nargo_cli/src/cli/test_cmd.rs b/tooling/nargo_cli/src/cli/test_cmd.rs index c8848e2e304..363b3205481 100644 --- a/tooling/nargo_cli/src/cli/test_cmd.rs +++ b/tooling/nargo_cli/src/cli/test_cmd.rs @@ -174,9 +174,7 @@ fn run_test + Default>( check_crate( &mut context, crate_id, - compile_options.deny_warnings, - compile_options.disable_macros, - compile_options.debug_comptime_in_file.as_deref(), + compile_options, ) .expect("Any errors should have occurred when collecting test functions"); @@ -240,10 +238,7 @@ fn get_tests_in_package( check_crate_and_report_errors( &mut context, crate_id, - compile_options.deny_warnings, - compile_options.disable_macros, - compile_options.silence_warnings, - compile_options.debug_comptime_in_file.as_deref(), + compile_options, )?; Ok(context