From ccfa69c24c94d657f7d0881203ada133ed5d2ef9 Mon Sep 17 00:00:00 2001 From: Aztec Bot <49558828+AztecBot@users.noreply.github.com> Date: Wed, 3 Jul 2024 07:10:07 -0400 Subject: [PATCH] feat: Sync from noir (#7288) Automated pull of development from the [noir](https://github.com/noir-lang/noir) programming language, a dependency of Aztec. BEGIN_COMMIT_OVERRIDE feat: Sync from aztec-packages (https://github.com/noir-lang/noir/pull/5387) feat: Implement trait dispatch in the comptime interpreter (https://github.com/noir-lang/noir/pull/5376) feat(lsp): allow function rename (https://github.com/noir-lang/noir/pull/4294) chore: use `mod.nr` files in stdlib (https://github.com/noir-lang/noir/pull/5379) fix: Replace std::HashMap with FxHashMap to fix frontend indeterminism (https://github.com/noir-lang/noir/pull/5385) fix: Remove panics in the interpreter when a builtin fails to type check (https://github.com/noir-lang/noir/pull/5382) fix: Replace expects in interpreter with errors (https://github.com/noir-lang/noir/pull/5383) END_COMMIT_OVERRIDE --------- Co-authored-by: Tom French Co-authored-by: Tom French <15848336+TomAFrench@users.noreply.github.com> --- .noir-sync-commit | 2 +- noir/noir-repo/Cargo.lock | 7 + .../compiler/noirc_frontend/Cargo.toml | 1 + .../src/elaborator/expressions.rs | 9 +- .../noirc_frontend/src/elaborator/mod.rs | 103 ++++---- .../noirc_frontend/src/elaborator/patterns.rs | 24 +- .../src/elaborator/statements.rs | 7 + .../noirc_frontend/src/elaborator/types.rs | 46 ++-- .../noirc_frontend/src/hir/comptime/errors.rs | 16 +- .../src/hir/comptime/interpreter.rs | 129 +++++++-- .../src/hir/comptime/interpreter/builtin.rs | 130 +++++---- .../src/hir/def_collector/dc_crate.rs | 30 ++- .../src/hir/def_collector/dc_mod.rs | 8 +- .../src/hir/resolution/resolver.rs | 2 +- .../src/hir/type_check/errors.rs | 75 ++++-- .../noirc_frontend/src/hir/type_check/expr.rs | 25 +- .../noirc_frontend/src/hir/type_check/mod.rs | 2 +- .../noirc_frontend/src/hir_def/traits.rs | 2 +- .../compiler/noirc_frontend/src/lib.rs | 1 + .../compiler/noirc_frontend/src/locations.rs | 122 +++++++++ .../src/monomorphization/mod.rs | 191 +++++++------- .../noirc_frontend/src/node_interner.rs | 74 +++++- noir/noir-repo/cspell.json | 4 + .../cryptographic_primitives/ec_primitives.md | 4 +- .../cryptographic_primitives/hashes.mdx | 12 +- .../{collections.nr => collections/mod.nr} | 0 .../src/ec/{consts.nr => consts/mod.nr} | 0 .../noir_stdlib/src/{ec.nr => ec/mod.nr} | 0 .../src/{field.nr => field/mod.nr} | 0 .../noir_stdlib/src/{hash.nr => hash/mod.nr} | 0 .../src/hash/{poseidon.nr => poseidon/mod.nr} | 0 .../noir_stdlib/src/{meta.nr => meta/mod.nr} | 0 .../noir_stdlib/src/{ops.nr => ops/mod.nr} | 0 .../comptime_traits/Nargo.toml | 7 + .../comptime_traits/src/main.nr | 15 ++ noir/noir-repo/tooling/lsp/src/lib.rs | 14 +- .../lsp/src/requests/goto_definition.rs | 57 ++-- .../noir-repo/tooling/lsp/src/requests/mod.rs | 12 +- .../tooling/lsp/src/requests/rename.rs | 249 ++++++++++++++++++ noir/noir-repo/tooling/lsp/src/test_utils.rs | 39 +++ noir/noir-repo/tooling/lsp/src/types.rs | 7 +- .../test_programs/go_to_definition/Nargo.toml | 6 + .../go_to_definition/src/main.nr | 11 + .../lsp/test_programs/rename/Nargo.toml | 6 + .../lsp/test_programs/rename/src/main.nr | 22 ++ .../test_programs/rename_qualified/Nargo.toml | 6 + .../rename_qualified/src/main.nr | 9 + noir/noir-repo/tooling/nargo_cli/build.rs | 3 +- noir/scripts/sync-in-fixup.sh | 3 +- noir/verify_honk_proof/Prover.toml | 2 +- 50 files changed, 1154 insertions(+), 340 deletions(-) create mode 100644 noir/noir-repo/compiler/noirc_frontend/src/locations.rs rename noir/noir-repo/noir_stdlib/src/{collections.nr => collections/mod.nr} (100%) rename noir/noir-repo/noir_stdlib/src/ec/{consts.nr => consts/mod.nr} (100%) rename noir/noir-repo/noir_stdlib/src/{ec.nr => ec/mod.nr} (100%) rename noir/noir-repo/noir_stdlib/src/{field.nr => field/mod.nr} (100%) rename noir/noir-repo/noir_stdlib/src/{hash.nr => hash/mod.nr} (100%) rename noir/noir-repo/noir_stdlib/src/hash/{poseidon.nr => poseidon/mod.nr} (100%) rename noir/noir-repo/noir_stdlib/src/{meta.nr => meta/mod.nr} (100%) rename noir/noir-repo/noir_stdlib/src/{ops.nr => ops/mod.nr} (100%) create mode 100644 noir/noir-repo/test_programs/compile_success_empty/comptime_traits/Nargo.toml create mode 100644 noir/noir-repo/test_programs/compile_success_empty/comptime_traits/src/main.nr create mode 100644 noir/noir-repo/tooling/lsp/src/requests/rename.rs create mode 100644 noir/noir-repo/tooling/lsp/src/test_utils.rs create mode 100644 noir/noir-repo/tooling/lsp/test_programs/go_to_definition/Nargo.toml create mode 100644 noir/noir-repo/tooling/lsp/test_programs/go_to_definition/src/main.nr create mode 100644 noir/noir-repo/tooling/lsp/test_programs/rename/Nargo.toml create mode 100644 noir/noir-repo/tooling/lsp/test_programs/rename/src/main.nr create mode 100644 noir/noir-repo/tooling/lsp/test_programs/rename_qualified/Nargo.toml create mode 100644 noir/noir-repo/tooling/lsp/test_programs/rename_qualified/src/main.nr diff --git a/.noir-sync-commit b/.noir-sync-commit index 7f0f18023f8..c288f5b3cd9 100644 --- a/.noir-sync-commit +++ b/.noir-sync-commit @@ -1 +1 @@ -7b77bbfc19c51829814149e623257a3424d8e8c2 +32029f91f6aae4d2f6b08b4ea40481f5837e50bc diff --git a/noir/noir-repo/Cargo.lock b/noir/noir-repo/Cargo.lock index 589c3d179d8..17778d09d37 100644 --- a/noir/noir-repo/Cargo.lock +++ b/noir/noir-repo/Cargo.lock @@ -2917,6 +2917,7 @@ dependencies = [ "num-bigint", "num-traits", "petgraph", + "rangemap", "regex", "rustc-hash", "serde", @@ -3564,6 +3565,12 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "rangemap" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "977b1e897f9d764566891689e642653e5ed90c6895106acd005eb4c1d0203991" + [[package]] name = "rayon" version = "1.8.0" diff --git a/noir/noir-repo/compiler/noirc_frontend/Cargo.toml b/noir/noir-repo/compiler/noirc_frontend/Cargo.toml index cc5a9b1e652..052d2c5f484 100644 --- a/noir/noir-repo/compiler/noirc_frontend/Cargo.toml +++ b/noir/noir-repo/compiler/noirc_frontend/Cargo.toml @@ -29,6 +29,7 @@ regex = "1.9.1" cfg-if = "1.0.0" tracing.workspace = true petgraph = "0.6" +rangemap = "1.4.0" lalrpop-util = { version = "0.20.2", features = ["lexer"] } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs index 7d304990dd8..9c72529e11a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/expressions.rs @@ -547,7 +547,7 @@ impl<'context> Elaborator<'context> { trait_id: trait_id.trait_id, trait_generics: Vec::new(), }; - self.trait_constraints.push((constraint, expr_id)); + self.push_trait_constraint(constraint, expr_id); self.type_check_operator_method(expr_id, trait_id, &lhs_type, span); } typ @@ -663,7 +663,14 @@ impl<'context> Elaborator<'context> { } fn elaborate_comptime_block(&mut self, block: BlockExpression, span: Span) -> (ExprId, Type) { + // We have to push a new FunctionContext so that we can resolve any constraints + // in this comptime block early before the function as a whole finishes elaborating. + // Otherwise the interpreter below may find expressions for which the underlying trait + // call is not yet solved for. + self.function_context.push(Default::default()); let (block, _typ) = self.elaborate_block_expression(block); + self.check_and_pop_function_context(); + let mut interpreter = Interpreter::new(self.interner, &mut self.comptime_scopes, self.crate_id); let value = interpreter.evaluate_block(block); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs index e0671d6f7ff..4b4cf33aa2a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/mod.rs @@ -138,16 +138,14 @@ pub struct Elaborator<'context> { current_function: Option, - /// All type variables created in the current function. - /// This map is used to default any integer type variables at the end of - /// a function (before checking trait constraints) if a type wasn't already chosen. - type_variables: Vec, - - /// Trait constraints are collected during type checking until they are - /// verified at the end of a function. This is because constraints arise - /// on each variable, but it is only until function calls when the types - /// needed for the trait constraint may become known. - trait_constraints: Vec<(TraitConstraint, ExprId)>, + /// This is a stack of function contexts. Most of the time, for each function we + /// expect this to be of length one, containing each type variable and trait constraint + /// used in the function. This is also pushed to when a `comptime {}` block is used within + /// the function. Since it can force us to resolve that block's trait constraints earlier + /// so that they are resolved when the interpreter is run before the enclosing function + /// is finished elaborating. When this happens, we need to resolve any type variables + /// that were made within this block as well so that we can solve these traits. + function_context: Vec, /// The current module this elaborator is in. /// Initially empty, it is set whenever a new top-level item is resolved. @@ -166,6 +164,20 @@ pub struct Elaborator<'context> { unresolved_globals: BTreeMap, } +#[derive(Default)] +struct FunctionContext { + /// All type variables created in the current function. + /// This map is used to default any integer type variables at the end of + /// a function (before checking trait constraints) if a type wasn't already chosen. + type_variables: Vec, + + /// Trait constraints are collected during type checking until they are + /// verified at the end of a function. This is because constraints arise + /// on each variable, but it is only until function calls when the types + /// needed for the trait constraint may become known. + trait_constraints: Vec<(TraitConstraint, ExprId)>, +} + impl<'context> Elaborator<'context> { pub fn new(context: &'context mut Context, crate_id: CrateId) -> Self { Self { @@ -185,8 +197,7 @@ impl<'context> Elaborator<'context> { resolving_ids: BTreeSet::new(), trait_bounds: Vec::new(), current_function: None, - type_variables: Vec::new(), - trait_constraints: Vec::new(), + function_context: vec![FunctionContext::default()], current_trait_impl: None, comptime_scopes: vec![HashMap::default()], unresolved_globals: BTreeMap::new(), @@ -326,6 +337,7 @@ impl<'context> Elaborator<'context> { let func_meta = func_meta.clone(); self.trait_bounds = func_meta.trait_constraints.clone(); + self.function_context.push(FunctionContext::default()); // Introduce all numeric generics into scope for generic in &func_meta.all_generics { @@ -367,34 +379,11 @@ impl<'context> Elaborator<'context> { self.type_check_function_body(body_type, &func_meta, hir_func.as_expr()); } - // Default any type variables that still need defaulting. + // Default any type variables that still need defaulting and + // verify any remaining trait constraints arising from the function body. // This is done before trait impl search since leaving them bindable can lead to errors // when multiple impls are available. Instead we default first to choose the Field or u64 impl. - for typ in &self.type_variables { - if let Type::TypeVariable(variable, kind) = typ.follow_bindings() { - let msg = "TypeChecker should only track defaultable type vars"; - variable.bind(kind.default_type().expect(msg)); - } - } - - // Verify any remaining trait constraints arising from the function body - for (mut constraint, expr_id) in std::mem::take(&mut self.trait_constraints) { - let span = self.interner.expr_span(&expr_id); - - if matches!(&constraint.typ, Type::MutableReference(_)) { - let (_, dereferenced_typ) = - self.insert_auto_dereferences(expr_id, constraint.typ.clone()); - constraint.typ = dereferenced_typ; - } - - self.verify_trait_constraint( - &constraint.typ, - constraint.trait_id, - &constraint.trait_generics, - expr_id, - span, - ); - } + self.check_and_pop_function_context(); // Now remove all the `where` clause constraints we added for constraint in &func_meta.trait_constraints { @@ -417,12 +406,42 @@ impl<'context> Elaborator<'context> { meta.function_body = FunctionBody::Resolved; self.trait_bounds.clear(); - self.type_variables.clear(); self.interner.update_fn(id, hir_func); self.current_function = old_function; self.current_item = old_item; } + /// Defaults all type variables used in this function context then solves + /// all still-unsolved trait constraints in this context. + fn check_and_pop_function_context(&mut self) { + let context = self.function_context.pop().expect("Imbalanced function_context pushes"); + + for typ in context.type_variables { + if let Type::TypeVariable(variable, kind) = typ.follow_bindings() { + let msg = "TypeChecker should only track defaultable type vars"; + variable.bind(kind.default_type().expect(msg)); + } + } + + for (mut constraint, expr_id) in context.trait_constraints { + let span = self.interner.expr_span(&expr_id); + + if matches!(&constraint.typ, Type::MutableReference(_)) { + let (_, dereferenced_typ) = + self.insert_auto_dereferences(expr_id, constraint.typ.clone()); + constraint.typ = dereferenced_typ; + } + + self.verify_trait_constraint( + &constraint.typ, + constraint.trait_id, + &constraint.trait_generics, + expr_id, + span, + ); + } + } + /// This turns function parameters of the form: /// `fn foo(x: impl Bar)` /// @@ -1339,10 +1358,6 @@ impl<'context> Elaborator<'context> { self.elaborate_comptime_global(global_id); } - // Avoid defaulting the types of globals here since they may be used in any function. - // Otherwise we may prematurely default to a Field inside the next function if this - // global was unused there, even if it is consistently used as a u8 everywhere else. - self.type_variables.clear(); self.local_module = old_module; self.file = old_file; self.current_item = old_item; @@ -1494,7 +1509,7 @@ impl<'context> Elaborator<'context> { traits: BTreeMap::new(), trait_impls: Vec::new(), globals: Vec::new(), - impls: std::collections::HashMap::new(), + impls: rustc_hash::FxHashMap::default(), }; items.functions = function_sets; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs index 4f04f5c523c..8a2f305d8f6 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/patterns.rs @@ -14,7 +14,7 @@ use crate::{ stmt::HirPattern, }, macros_api::{HirExpression, Ident, Path, Pattern}, - node_interner::{DefinitionId, DefinitionKind, ExprId, GlobalId, TraitImplKind}, + node_interner::{DefinitionId, DefinitionKind, DependencyId, ExprId, GlobalId, TraitImplKind}, Shared, StructType, Type, TypeBindings, }; @@ -396,6 +396,7 @@ impl<'context> Elaborator<'context> { let expr = self.resolve_variable(variable); let id = self.interner.push_expr(HirExpression::Ident(expr.clone(), generics.clone())); + self.interner.push_expr_location(id, span, self.file); let typ = self.type_check_variable(expr, id, generics); self.interner.push_expr_type(id, typ.clone()); @@ -418,10 +419,14 @@ impl<'context> Elaborator<'context> { if hir_ident.id != DefinitionId::dummy_id() { match self.interner.definition(hir_ident.id).kind { - DefinitionKind::Function(id) => { + DefinitionKind::Function(func_id) => { if let Some(current_item) = self.current_item { - self.interner.add_function_dependency(current_item, id); + self.interner.add_function_dependency(current_item, func_id); } + + let variable = DependencyId::Variable(hir_ident.location); + let function = DependencyId::Function(func_id); + self.interner.add_reference(function, variable); } DefinitionKind::Global(global_id) => { if let Some(global) = self.unresolved_globals.remove(&global_id) { @@ -430,6 +435,10 @@ impl<'context> Elaborator<'context> { if let Some(current_item) = self.current_item { self.interner.add_global_dependency(current_item, global_id); } + + let variable = DependencyId::Variable(hir_ident.location); + let global = DependencyId::Global(global_id); + self.interner.add_reference(global, variable); } DefinitionKind::GenericType(_) => { // Initialize numeric generics to a polymorphic integer type in case @@ -516,7 +525,7 @@ impl<'context> Elaborator<'context> { for mut constraint in function.trait_constraints.clone() { constraint.apply_bindings(&bindings); - self.trait_constraints.push((constraint, expr_id)); + self.push_trait_constraint(constraint, expr_id); } } } @@ -533,7 +542,7 @@ impl<'context> Elaborator<'context> { // Currently only one impl can be selected per expr_id, so this // constraint needs to be pushed after any other constraints so // that monomorphization can resolve this trait method to the correct impl. - self.trait_constraints.push((constraint, expr_id)); + self.push_trait_constraint(constraint, expr_id); } } @@ -575,7 +584,10 @@ impl<'context> Elaborator<'context> { } pub fn get_ident_from_path(&mut self, path: Path) -> (HirIdent, usize) { - let location = Location::new(path.span(), self.file); + let location = Location::new( + path.segments.last().expect("ice: path without segments").span(), + self.file, + ); let error = match path.as_ident().map(|ident| self.use_variable(ident)) { Some(Ok(found)) => return found, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs index 0d67c9ed3e3..e2d44919c5e 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/statements.rs @@ -433,8 +433,15 @@ impl<'context> Elaborator<'context> { } fn elaborate_comptime_statement(&mut self, statement: Statement) -> (HirStatement, Type) { + // We have to push a new FunctionContext so that we can resolve any constraints + // in this comptime block early before the function as a whole finishes elaborating. + // Otherwise the interpreter below may find expressions for which the underlying trait + // call is not yet solved for. + self.function_context.push(Default::default()); let span = statement.span; let (hir_statement, _typ) = self.elaborate_statement(statement); + self.check_and_pop_function_context(); + let mut interpreter = Interpreter::new(self.interner, &mut self.comptime_scopes, self.crate_id); let value = interpreter.evaluate_statement(hir_statement); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs index 63cab40f9d3..7f07e2a9538 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/elaborator/types.rs @@ -16,7 +16,7 @@ use crate::{ errors::ResolverError, resolver::{verify_mutable_reference, SELF_TYPE_NAME, WILDCARD_TYPE}, }, - type_check::{Source, TypeCheckError}, + type_check::{NoMatchingImplFoundError, Source, TypeCheckError}, }, hir_def::{ expr::{ @@ -615,7 +615,7 @@ impl<'context> Elaborator<'context> { /// in self.type_variables to default it later. pub(super) fn polymorphic_integer_or_field(&mut self) -> Type { let typ = Type::polymorphic_integer_or_field(self.interner); - self.type_variables.push(typ.clone()); + self.push_type_variable(typ.clone()); typ } @@ -623,7 +623,7 @@ impl<'context> Elaborator<'context> { /// in self.type_variables to default it later. pub(super) fn polymorphic_integer(&mut self) -> Type { let typ = Type::polymorphic_integer(self.interner); - self.type_variables.push(typ.clone()); + self.push_type_variable(typ.clone()); typ } @@ -1410,26 +1410,10 @@ impl<'context> Elaborator<'context> { Err(erroring_constraints) => { if erroring_constraints.is_empty() { self.push_err(TypeCheckError::TypeAnnotationsNeeded { span }); - } else { - // Don't show any errors where try_get_trait returns None. - // This can happen if a trait is used that was never declared. - let constraints = erroring_constraints - .into_iter() - .map(|constraint| { - let r#trait = self.interner.try_get_trait(constraint.trait_id)?; - let mut name = r#trait.name.to_string(); - if !constraint.trait_generics.is_empty() { - let generics = - vecmap(&constraint.trait_generics, ToString::to_string); - name += &format!("<{}>", generics.join(", ")); - } - Some((constraint.typ, name)) - }) - .collect::>>(); - - if let Some(constraints) = constraints { - self.push_err(TypeCheckError::NoMatchingImplFound { constraints, span }); - } + } else if let Some(error) = + NoMatchingImplFoundError::new(self.interner, erroring_constraints, span) + { + self.push_err(TypeCheckError::NoMatchingImplFound(error)); } } } @@ -1557,4 +1541,20 @@ impl<'context> Elaborator<'context> { } } } + + /// Push a type variable into the current FunctionContext to be defaulted if needed + /// at the end of the earlier of either the current function or the current comptime scope. + fn push_type_variable(&mut self, typ: Type) { + let context = self.function_context.last_mut(); + let context = context.expect("The function_context stack should always be non-empty"); + context.type_variables.push(typ); + } + + /// Push a trait constraint into the current FunctionContext to be solved if needed + /// at the end of the earlier of either the current function or the current comptime scope. + pub fn push_trait_constraint(&mut self, constraint: TraitConstraint, expr_id: ExprId) { + let context = self.function_context.last_mut(); + let context = context.expect("The function_context stack should always be non-empty"); + context.trait_constraints.push((constraint, expr_id)); + } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs index d2c7acee2a3..9bc54cf0e04 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/errors.rs @@ -1,7 +1,10 @@ use std::rc::Rc; use crate::{ - hir::def_collector::dc_crate::CompilationError, parser::ParserError, token::Tokens, Type, + hir::{def_collector::dc_crate::CompilationError, type_check::NoMatchingImplFoundError}, + parser::ParserError, + token::Tokens, + Type, }; use acvm::{acir::AcirField, FieldElement}; use fm::FileId; @@ -44,6 +47,8 @@ pub enum InterpreterError { FailedToParseMacro { error: ParserError, tokens: Rc, rule: &'static str, file: FileId }, UnsupportedTopLevelItemUnquote { item: String, location: Location }, NonComptimeFnCallInSameCrate { function: String, location: Location }, + NoImpl { location: Location }, + NoMatchingImplFound { error: NoMatchingImplFoundError, file: FileId }, Unimplemented { item: String, location: Location }, @@ -106,11 +111,15 @@ impl InterpreterError { | InterpreterError::UnsupportedTopLevelItemUnquote { location, .. } | InterpreterError::NonComptimeFnCallInSameCrate { location, .. } | InterpreterError::Unimplemented { location, .. } + | InterpreterError::NoImpl { location, .. } | InterpreterError::BreakNotInLoop { location, .. } | InterpreterError::ContinueNotInLoop { location, .. } => *location, InterpreterError::FailedToParseMacro { error, file, .. } => { Location::new(error.span(), *file) } + InterpreterError::NoMatchingImplFound { error, file } => { + Location::new(error.span, *file) + } InterpreterError::Break | InterpreterError::Continue => { panic!("Tried to get the location of Break/Continue error!") } @@ -324,6 +333,11 @@ impl<'a> From<&'a InterpreterError> for CustomDiagnostic { let msg = "There is no loop to continue!".into(); CustomDiagnostic::simple_error(msg, String::new(), location.span) } + InterpreterError::NoImpl { location } => { + let msg = "No impl found due to prior type error".into(); + CustomDiagnostic::simple_error(msg, String::new(), location.span) + } + InterpreterError::NoMatchingImplFound { error, .. } => error.into(), InterpreterError::Break => unreachable!("Uncaught InterpreterError::Break"), InterpreterError::Continue => unreachable!("Uncaught InterpreterError::Continue"), } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs index d2b98569bbb..1b168e40043 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter.rs @@ -8,7 +8,12 @@ use rustc_hash::FxHashMap as HashMap; use crate::ast::{BinaryOpKind, FunctionKind, IntegerBitSize, Signedness}; use crate::graph::CrateId; -use crate::monomorphization::{perform_instantiation_bindings, undo_instantiation_bindings}; +use crate::hir_def::expr::ImplKind; +use crate::macros_api::UnaryOp; +use crate::monomorphization::{ + perform_impl_bindings, perform_instantiation_bindings, resolve_trait_method, + undo_instantiation_bindings, +}; use crate::token::Tokens; use crate::{ hir_def::{ @@ -66,8 +71,12 @@ impl<'a> Interpreter<'a> { instantiation_bindings: TypeBindings, location: Location, ) -> IResult { + let trait_method = self.interner.get_trait_method_id(function); + perform_instantiation_bindings(&instantiation_bindings); + let impl_bindings = perform_impl_bindings(self.interner, trait_method, function); let result = self.call_function_inner(function, arguments, location); + undo_instantiation_bindings(impl_bindings); undo_instantiation_bindings(instantiation_bindings); result } @@ -347,6 +356,13 @@ impl<'a> Interpreter<'a> { pub(super) fn evaluate_ident(&mut self, ident: HirIdent, id: ExprId) -> IResult { let definition = self.interner.definition(ident.id); + if let ImplKind::TraitMethod(method, _, _) = ident.impl_kind { + let method_id = resolve_trait_method(self.interner, method, id)?; + let typ = self.interner.id_type(id).follow_bindings(); + let bindings = self.interner.get_instantiation_bindings(id).clone(); + return Ok(Value::Function(method_id, typ, Rc::new(bindings))); + } + match &definition.kind { DefinitionKind::Function(function_id) => { let typ = self.interner.id_type(id).follow_bindings(); @@ -556,8 +572,17 @@ impl<'a> Interpreter<'a> { fn evaluate_prefix(&mut self, prefix: HirPrefixExpression, id: ExprId) -> IResult { let rhs = self.evaluate(prefix.rhs)?; - match prefix.operator { - crate::ast::UnaryOp::Minus => match rhs { + self.evaluate_prefix_with_value(rhs, prefix.operator, id) + } + + fn evaluate_prefix_with_value( + &mut self, + rhs: Value, + operator: UnaryOp, + id: ExprId, + ) -> IResult { + match operator { + UnaryOp::Minus => match rhs { Value::Field(value) => Ok(Value::Field(FieldElement::zero() - value)), Value::I8(value) => Ok(Value::I8(-value)), Value::I16(value) => Ok(Value::I16(-value)), @@ -573,7 +598,7 @@ impl<'a> Interpreter<'a> { Err(InterpreterError::InvalidValueForUnary { value, location, operator }) } }, - crate::ast::UnaryOp::Not => match rhs { + UnaryOp::Not => match rhs { Value::Bool(value) => Ok(Value::Bool(!value)), Value::I8(value) => Ok(Value::I8(!value)), Value::I16(value) => Ok(Value::I16(!value)), @@ -588,8 +613,8 @@ impl<'a> Interpreter<'a> { Err(InterpreterError::InvalidValueForUnary { value, location, operator: "not" }) } }, - crate::ast::UnaryOp::MutableReference => Ok(Value::Pointer(Shared::new(rhs))), - crate::ast::UnaryOp::Dereference { implicitly_added: _ } => match rhs { + UnaryOp::MutableReference => Ok(Value::Pointer(Shared::new(rhs))), + UnaryOp::Dereference { implicitly_added: _ } => match rhs { Value::Pointer(element) => Ok(element.borrow().clone()), value => { let location = self.interner.expr_location(&id); @@ -603,13 +628,8 @@ impl<'a> Interpreter<'a> { let lhs = self.evaluate(infix.lhs)?; let rhs = self.evaluate(infix.rhs)?; - // TODO: Need to account for operator overloading - // See https://github.com/noir-lang/noir/issues/4925 if self.interner.get_selected_impl_for_expression(id).is_some() { - return Err(InterpreterError::Unimplemented { - item: "Operator overloading in the interpreter".to_string(), - location: infix.operator.location, - }); + return self.evaluate_overloaded_infix(infix, lhs, rhs, id); } use InterpreterError::InvalidValuesForBinary; @@ -854,6 +874,64 @@ impl<'a> Interpreter<'a> { } } + fn evaluate_overloaded_infix( + &mut self, + infix: HirInfixExpression, + lhs: Value, + rhs: Value, + id: ExprId, + ) -> IResult { + let method = infix.trait_method_id; + let operator = infix.operator.kind; + + let method_id = resolve_trait_method(self.interner, method, id)?; + let type_bindings = self.interner.get_instantiation_bindings(id).clone(); + + let lhs = (lhs, self.interner.expr_location(&infix.lhs)); + let rhs = (rhs, self.interner.expr_location(&infix.rhs)); + + let location = self.interner.expr_location(&id); + let value = self.call_function(method_id, vec![lhs, rhs], type_bindings, location)?; + + // Certain operators add additional operations after the trait call: + // - `!=`: Reverse the result of Eq + // - Comparator operators: Convert the returned `Ordering` to a boolean. + use BinaryOpKind::*; + match operator { + NotEqual => self.evaluate_prefix_with_value(value, UnaryOp::Not, id), + Less | LessEqual | Greater | GreaterEqual => self.evaluate_ordering(value, operator), + _ => Ok(value), + } + } + + /// Given the result of a `cmp` operation, convert it into the boolean result of the given operator. + /// - `<`: `ordering == Ordering::Less` + /// - `<=`: `ordering != Ordering::Greater` + /// - `>`: `ordering == Ordering::Greater` + /// - `<=`: `ordering != Ordering::Less` + fn evaluate_ordering(&self, ordering: Value, operator: BinaryOpKind) -> IResult { + let ordering = match ordering { + Value::Struct(fields, _) => match fields.into_iter().next().unwrap().1 { + Value::Field(ordering) => ordering, + _ => unreachable!("`cmp` should always return an Ordering value"), + }, + _ => unreachable!("`cmp` should always return an Ordering value"), + }; + + use BinaryOpKind::*; + let less_or_greater = if matches!(operator, Less | GreaterEqual) { + FieldElement::zero() // Ordering::Less + } else { + 2u128.into() // Ordering::Greater + }; + + if matches!(operator, Less | Greater) { + Ok(Value::Bool(ordering == less_or_greater)) + } else { + Ok(Value::Bool(ordering != less_or_greater)) + } + } + fn evaluate_index(&mut self, index: HirIndexExpression, id: ExprId) -> IResult { let array = self.evaluate(index.collection)?; let index = self.evaluate(index.index)?; @@ -882,7 +960,10 @@ impl<'a> Interpreter<'a> { let index = match index { Value::Field(value) => { - value.try_to_u64().expect("index could not fit into u64") as usize + value.try_to_u64().and_then(|value| value.try_into().ok()).ok_or_else(|| { + let typ = Type::default_int_type(); + InterpreterError::IntegerOutOfRangeForType { value, typ, location } + })? } Value::I8(value) => value as usize, Value::I16(value) => value as usize, @@ -1209,8 +1290,15 @@ impl<'a> Interpreter<'a> { } } HirLValue::MemberAccess { object, field_name, field_index, typ: _, location } => { - let index = field_index.expect("The field index should be set after type checking"); - match self.evaluate_lvalue(&object)? { + let object_value = self.evaluate_lvalue(&object)?; + + let index = field_index.ok_or_else(|| { + let value = object_value.clone(); + let field_name = field_name.to_string(); + InterpreterError::ExpectedStructToHaveField { value, field_name, location } + })?; + + match object_value { Value::Tuple(mut fields) => { fields[index] = rhs; self.store_lvalue(*object, Value::Tuple(fields)) @@ -1254,9 +1342,16 @@ impl<'a> Interpreter<'a> { } } HirLValue::MemberAccess { object, field_name, field_index, typ: _, location } => { - let index = field_index.expect("The field index should be set after type checking"); + let object_value = self.evaluate_lvalue(object)?; + + let index = field_index.ok_or_else(|| { + let value = object_value.clone(); + let field_name = field_name.to_string(); + let location = *location; + InterpreterError::ExpectedStructToHaveField { value, field_name, location } + })?; - match self.evaluate_lvalue(object)? { + match object_value { Value::Tuple(mut values) => Ok(values.swap_remove(index)), Value::Struct(fields, _) => Ok(fields[&field_name.0.contents].clone()), value => Err(InterpreterError::NonTupleOrStructInMemberAccess { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs index 8523e13aeea..89c0b1d438e 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/comptime/interpreter/builtin.rs @@ -16,12 +16,12 @@ pub(super) fn call_builtin( location: Location, ) -> IResult { match name { - "array_len" => array_len(&arguments), - "as_slice" => as_slice(arguments), - "slice_push_back" => slice_push_back(arguments), - "struct_def_as_type" => struct_def_as_type(interner, arguments), - "struct_def_generics" => struct_def_generics(interner, arguments), - "struct_def_fields" => struct_def_fields(interner, arguments), + "array_len" => array_len(interner, arguments, location), + "as_slice" => as_slice(interner, arguments, location), + "slice_push_back" => slice_push_back(interner, arguments, location), + "struct_def_as_type" => struct_def_as_type(interner, arguments, location), + "struct_def_generics" => struct_def_generics(interner, arguments, location), + "struct_def_fields" => struct_def_fields(interner, arguments, location), _ => { let item = format!("Comptime evaluation for builtin function {name}"); Err(InterpreterError::Unimplemented { item, location }) @@ -29,27 +29,61 @@ pub(super) fn call_builtin( } } -fn array_len(arguments: &[(Value, Location)]) -> IResult { - assert_eq!(arguments.len(), 1, "ICE: `array_len` should only receive a single argument"); - match &arguments[0].0 { +fn check_argument_count( + expected: usize, + arguments: &[(Value, Location)], + location: Location, +) -> IResult<()> { + if arguments.len() == expected { + Ok(()) + } else { + let actual = arguments.len(); + Err(InterpreterError::ArgumentCountMismatch { expected, actual, location }) + } +} + +fn array_len( + interner: &NodeInterner, + mut arguments: Vec<(Value, Location)>, + location: Location, +) -> IResult { + check_argument_count(1, &arguments, location)?; + + match arguments.pop().unwrap().0 { Value::Array(values, _) | Value::Slice(values, _) => Ok(Value::U32(values.len() as u32)), - // Type checking should prevent this branch being taken. - _ => unreachable!("ICE: Cannot query length of types other than arrays or slices"), + value => { + let type_var = Box::new(interner.next_type_variable()); + let expected = Type::Array(type_var.clone(), type_var); + Err(InterpreterError::TypeMismatch { expected, value, location }) + } } } -fn as_slice(mut arguments: Vec<(Value, Location)>) -> IResult { - assert_eq!(arguments.len(), 1, "ICE: `as_slice` should only receive a single argument"); +fn as_slice( + interner: &NodeInterner, + mut arguments: Vec<(Value, Location)>, + location: Location, +) -> IResult { + check_argument_count(1, &arguments, location)?; + let (array, _) = arguments.pop().unwrap(); match array { Value::Array(values, Type::Array(_, typ)) => Ok(Value::Slice(values, Type::Slice(typ))), - // Type checking should prevent this branch being taken. - _ => unreachable!("ICE: Cannot convert types other than arrays into slices"), + value => { + let type_var = Box::new(interner.next_type_variable()); + let expected = Type::Array(type_var.clone(), type_var); + Err(InterpreterError::TypeMismatch { expected, value, location }) + } } } -fn slice_push_back(mut arguments: Vec<(Value, Location)>) -> IResult { - assert_eq!(arguments.len(), 2, "ICE: `slice_push_back` should only receive two arguments"); +fn slice_push_back( + interner: &NodeInterner, + mut arguments: Vec<(Value, Location)>, + location: Location, +) -> IResult { + check_argument_count(2, &arguments, location)?; + let (element, _) = arguments.pop().unwrap(); let (slice, _) = arguments.pop().unwrap(); match slice { @@ -57,8 +91,11 @@ fn slice_push_back(mut arguments: Vec<(Value, Location)>) -> IResult { values.push_back(element); Ok(Value::Slice(values, typ)) } - // Type checking should prevent this branch being taken. - _ => unreachable!("ICE: `slice_push_back` expects a slice as its first argument"), + value => { + let type_var = Box::new(interner.next_type_variable()); + let expected = Type::Slice(type_var); + Err(InterpreterError::TypeMismatch { expected, value, location }) + } } } @@ -66,12 +103,15 @@ fn slice_push_back(mut arguments: Vec<(Value, Location)>) -> IResult { fn struct_def_as_type( interner: &NodeInterner, mut arguments: Vec<(Value, Location)>, + location: Location, ) -> IResult { - assert_eq!(arguments.len(), 1, "ICE: `generics` should only receive a single argument"); - let (struct_def, span) = match arguments.pop() { - Some((Value::StructDefinition(id), location)) => (id, location.span), - other => { - unreachable!("ICE: `as_type` expected a `StructDefinition` argument, found {other:?}") + check_argument_count(1, &arguments, location)?; + + let (struct_def, span) = match arguments.pop().unwrap() { + (Value::StructDefinition(id), location) => (id, location.span), + value => { + let expected = Type::Quoted(QuotedType::StructDefinition); + return Err(InterpreterError::TypeMismatch { expected, location, value: value.0 }); } }; @@ -95,29 +135,28 @@ fn struct_def_as_type( fn struct_def_generics( interner: &NodeInterner, mut arguments: Vec<(Value, Location)>, + location: Location, ) -> IResult { - assert_eq!(arguments.len(), 1, "ICE: `generics` should only receive a single argument"); - let (struct_def, span) = match arguments.pop() { - Some((Value::StructDefinition(id), location)) => (id, location.span), - other => { - unreachable!("ICE: `as_type` expected a `StructDefinition` argument, found {other:?}") + check_argument_count(1, &arguments, location)?; + + let (struct_def, span) = match arguments.pop().unwrap() { + (Value::StructDefinition(id), location) => (id, location.span), + value => { + let expected = Type::Quoted(QuotedType::StructDefinition); + return Err(InterpreterError::TypeMismatch { expected, location, value: value.0 }); } }; let struct_def = interner.get_struct(struct_def); + let struct_def = struct_def.borrow(); - let generics = struct_def - .borrow() - .generics - .iter() - .map(|generic| { - let name = SpannedToken::new(Token::Ident(generic.type_var.borrow().to_string()), span); - Value::Code(Rc::new(Tokens(vec![name]))) - }) - .collect(); + let generics = struct_def.generics.iter().map(|generic| { + let name = SpannedToken::new(Token::Ident(generic.type_var.borrow().to_string()), span); + Value::Code(Rc::new(Tokens(vec![name]))) + }); let typ = Type::Slice(Box::new(Type::Quoted(QuotedType::Quoted))); - Ok(Value::Slice(generics, typ)) + Ok(Value::Slice(generics.collect(), typ)) } /// fn fields(self) -> [(Quoted, Quoted)] @@ -125,12 +164,15 @@ fn struct_def_generics( fn struct_def_fields( interner: &mut NodeInterner, mut arguments: Vec<(Value, Location)>, + location: Location, ) -> IResult { - assert_eq!(arguments.len(), 1, "ICE: `generics` should only receive a single argument"); - let (struct_def, span) = match arguments.pop() { - Some((Value::StructDefinition(id), location)) => (id, location.span), - other => { - unreachable!("ICE: `as_type` expected a `StructDefinition` argument, found {other:?}") + check_argument_count(1, &arguments, location)?; + + let (struct_def, span) = match arguments.pop().unwrap() { + (Value::StructDefinition(id), location) => (id, location.span), + value => { + let expected = Type::Quoted(QuotedType::StructDefinition); + return Err(InterpreterError::TypeMismatch { expected, location, value: value.0 }); } }; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 37ece01c805..6858e10a175 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -20,18 +20,20 @@ use crate::hir::Context; use crate::macros_api::{MacroError, MacroProcessor}; use crate::node_interner::{ - FuncId, GlobalId, NodeInterner, StructId, TraitId, TraitImplId, TypeAliasId, + DependencyId, FuncId, GlobalId, NodeInterner, StructId, TraitId, TraitImplId, TypeAliasId, }; use crate::ast::{ ExpressionKind, Ident, LetStatement, Literal, NoirFunction, NoirStruct, NoirTrait, NoirTypeAlias, Path, PathKind, UnresolvedGenerics, UnresolvedTraitConstraint, UnresolvedType, }; + use crate::parser::{ParserError, SortedModule}; use fm::FileId; use iter_extended::vecmap; -use noirc_errors::{CustomDiagnostic, Span}; -use std::collections::{BTreeMap, HashMap}; +use noirc_errors::{CustomDiagnostic, Location, Span}; +use rustc_hash::FxHashMap as HashMap; +use std::collections::BTreeMap; use std::vec; @@ -253,7 +255,7 @@ impl DefCollector { types: BTreeMap::new(), type_aliases: BTreeMap::new(), traits: BTreeMap::new(), - impls: HashMap::new(), + impls: HashMap::default(), globals: vec![], trait_impls: vec![], }, @@ -327,6 +329,7 @@ impl DefCollector { // Resolve unresolved imports collected from the crate, one by one. for collected_import in std::mem::take(&mut def_collector.imports) { + let module_id = collected_import.module_id; match resolve_import(crate_id, &collected_import, &context.def_maps) { Ok(resolved_import) => { if let Some(error) = resolved_import.error { @@ -344,6 +347,9 @@ impl DefCollector { let result = current_def_map.modules[resolved_import.module_scope.0] .import(name.clone(), ns, resolved_import.is_prelude); + let file_id = current_def_map.file_id(module_id); + add_import_reference(ns, &name, &mut context.def_interner, file_id); + if let Err((first_def, second_def)) = result { let err = DefCollectorErrorKind::Duplicate { typ: DuplicateType::Import, @@ -467,6 +473,22 @@ impl DefCollector { } } +fn add_import_reference( + def_id: crate::macros_api::ModuleDefId, + name: &Ident, + interner: &mut NodeInterner, + file_id: FileId, +) { + if name.span() == Span::empty(0) { + // We ignore empty spans at 0 location, this must be Stdlib + return; + } + if let crate::macros_api::ModuleDefId::FunctionId(func_id) = def_id { + let variable = DependencyId::Variable(Location::new(name.span(), file_id)); + interner.add_reference_for(DependencyId::Function(func_id), variable); + } +} + fn inject_prelude( crate_id: CrateId, context: &Context, diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index c9198a1d04c..aebc649b7b2 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -1,11 +1,12 @@ use std::path::Path; -use std::{collections::HashMap, vec}; +use std::vec; use acvm::{AcirField, FieldElement}; use fm::{FileId, FileManager, FILE_EXTENSION}; use noirc_errors::Location; use num_bigint::BigUint; use num_traits::Num; +use rustc_hash::FxHashMap as HashMap; use crate::ast::{ FunctionDefinition, Ident, ItemVisibility, LetStatement, ModuleDeclaration, NoirFunction, @@ -400,7 +401,7 @@ impl<'a> ModCollector<'a> { self_type: None, }; - let mut method_ids = HashMap::new(); + let mut method_ids = HashMap::default(); for trait_item in &trait_definition.items { match trait_item { TraitItem::Function { @@ -414,6 +415,7 @@ impl<'a> ModCollector<'a> { let func_id = context.def_interner.push_empty_fn(); method_ids.insert(name.to_string(), func_id); + let location = Location::new(name.span(), self.file_id); let modifiers = FunctionModifiers { name: name.to_string(), visibility: ItemVisibility::Public, @@ -422,9 +424,9 @@ impl<'a> ModCollector<'a> { is_unconstrained: false, generic_count: generics.len(), is_comptime: false, + name_location: location, }; - let location = Location::new(name.span(), self.file_id); context .def_interner .push_function_definition(func_id, modifiers, trait_id.0, location); diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs index 6d547aaf0b7..2eb33f7603f 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/resolution/resolver.rs @@ -1512,7 +1512,7 @@ impl<'a> Resolver<'a> { // Otherwise, then it is referring to an Identifier // This lookup allows support of such statements: let x = foo::bar::SOME_GLOBAL + 10; // If the expression is a singular indent, we search the resolver's current scope as normal. - let (hir_ident, var_scope_index) = self.get_ident_from_path(path); + let (hir_ident, var_scope_index) = self.get_ident_from_path(path.clone()); if hir_ident.id != DefinitionId::dummy_id() { match self.interner.definition(hir_ident.id).kind { diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs index f18e8a9e843..9c6a39d1940 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/errors.rs @@ -1,4 +1,5 @@ use acvm::FieldElement; +use iter_extended::vecmap; use noirc_errors::CustomDiagnostic as Diagnostic; use noirc_errors::Span; use thiserror::Error; @@ -6,7 +7,9 @@ use thiserror::Error; use crate::ast::{BinaryOpKind, FunctionReturnType, IntegerBitSize, Signedness}; use crate::hir::resolution::errors::ResolverError; use crate::hir_def::expr::HirBinaryOp; +use crate::hir_def::traits::TraitConstraint; use crate::hir_def::types::Type; +use crate::macros_api::NodeInterner; #[derive(Error, Debug, Clone, PartialEq, Eq)] pub enum Source { @@ -114,7 +117,7 @@ pub enum TypeCheckError { parameter_index: usize, }, #[error("No matching impl found")] - NoMatchingImplFound { constraints: Vec<(Type, String)>, span: Span }, + NoMatchingImplFound(NoMatchingImplFoundError), #[error("Constraint for `{typ}: {trait_name}` is not needed, another matching impl is already in scope")] UnneededTraitConstraint { trait_name: String, typ: Type, span: Span }, #[error( @@ -149,6 +152,12 @@ pub enum TypeCheckError { MacroReturningNonExpr { typ: Type, span: Span }, } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct NoMatchingImplFoundError { + constraints: Vec<(Type, String)>, + pub span: Span, +} + impl TypeCheckError { pub fn add_context(self, ctx: &'static str) -> Self { TypeCheckError::Context { err: Box::new(self), ctx } @@ -307,20 +316,7 @@ impl<'a> From<&'a TypeCheckError> for Diagnostic { let msg = format!("Unused expression result of type {expr_type}"); Diagnostic::simple_warning(msg, String::new(), *expr_span) } - TypeCheckError::NoMatchingImplFound { constraints, span } => { - assert!(!constraints.is_empty()); - let msg = format!("No matching impl found for `{}: {}`", constraints[0].0, constraints[0].1); - let mut diagnostic = Diagnostic::from_message(&msg); - - diagnostic.add_secondary(format!("No impl for `{}: {}`", constraints[0].0, constraints[0].1), *span); - - // These must be notes since secondaries are unordered - for (typ, trait_name) in &constraints[1..] { - diagnostic.add_note(format!("Required by `{typ}: {trait_name}`")); - } - - diagnostic - } + TypeCheckError::NoMatchingImplFound(error) => error.into(), TypeCheckError::UnneededTraitConstraint { trait_name, typ, span } => { let msg = format!("Constraint for `{typ}: {trait_name}` is not needed, another matching impl is already in scope"); Diagnostic::simple_warning(msg, "Unnecessary trait constraint in where clause".into(), *span) @@ -350,7 +346,54 @@ impl<'a> From<&'a TypeCheckError> for Diagnostic { format!("Expected macro call to return a `Quoted` but found a(n) `{typ}`"), "Macro calls must return quoted values, otherwise there is no code to insert".into(), *span, - ), + ), + } + } +} + +impl<'a> From<&'a NoMatchingImplFoundError> for Diagnostic { + fn from(error: &'a NoMatchingImplFoundError) -> Self { + let constraints = &error.constraints; + let span = error.span; + + assert!(!constraints.is_empty()); + let msg = + format!("No matching impl found for `{}: {}`", constraints[0].0, constraints[0].1); + let mut diagnostic = Diagnostic::from_message(&msg); + + let secondary = format!("No impl for `{}: {}`", constraints[0].0, constraints[0].1); + diagnostic.add_secondary(secondary, span); + + // These must be notes since secondaries are unordered + for (typ, trait_name) in &constraints[1..] { + diagnostic.add_note(format!("Required by `{typ}: {trait_name}`")); } + + diagnostic + } +} + +impl NoMatchingImplFoundError { + pub fn new( + interner: &NodeInterner, + failing_constraints: Vec, + span: Span, + ) -> Option { + // Don't show any errors where try_get_trait returns None. + // This can happen if a trait is used that was never declared. + let constraints = failing_constraints + .into_iter() + .map(|constraint| { + let r#trait = interner.try_get_trait(constraint.trait_id)?; + let mut name = r#trait.name.to_string(); + if !constraint.trait_generics.is_empty() { + let generics = vecmap(&constraint.trait_generics, ToString::to_string); + name += &format!("<{}>", generics.join(", ")); + } + Some((constraint.typ, name)) + }) + .collect::>>()?; + + Some(Self { constraints, span }) } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs index 77861a6d8f8..1f3e9103cde 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/expr.rs @@ -17,6 +17,7 @@ use crate::{ TypeBinding, TypeBindings, TypeVariableKind, }; +use super::NoMatchingImplFoundError; use super::{errors::TypeCheckError, TypeChecker}; impl<'interner> TypeChecker<'interner> { @@ -518,26 +519,10 @@ impl<'interner> TypeChecker<'interner> { Err(erroring_constraints) => { if erroring_constraints.is_empty() { self.errors.push(TypeCheckError::TypeAnnotationsNeeded { span }); - } else { - // Don't show any errors where try_get_trait returns None. - // This can happen if a trait is used that was never declared. - let constraints = erroring_constraints - .into_iter() - .map(|constraint| { - let r#trait = self.interner.try_get_trait(constraint.trait_id)?; - let mut name = r#trait.name.to_string(); - if !constraint.trait_generics.is_empty() { - let generics = - vecmap(&constraint.trait_generics, ToString::to_string); - name += &format!("<{}>", generics.join(", ")); - } - Some((constraint.typ, name)) - }) - .collect::>>(); - - if let Some(constraints) = constraints { - self.errors.push(TypeCheckError::NoMatchingImplFound { constraints, span }); - } + } else if let Some(error) = + NoMatchingImplFoundError::new(self.interner, erroring_constraints, span) + { + self.errors.push(TypeCheckError::NoMatchingImplFound(error)); } } } diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs index 1d3c7fcda9b..b8fd59e015b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir/type_check/mod.rs @@ -11,7 +11,7 @@ mod errors; mod expr; mod stmt; -pub use errors::TypeCheckError; +pub use errors::{NoMatchingImplFoundError, TypeCheckError}; use noirc_errors::Span; use crate::{ diff --git a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/traits.rs b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/traits.rs index e4959cb3dd9..0600706922b 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/hir_def/traits.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/hir_def/traits.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use rustc_hash::FxHashMap as HashMap; use crate::ast::{Ident, NoirFunction}; use crate::{ diff --git a/noir/noir-repo/compiler/noirc_frontend/src/lib.rs b/noir/noir-repo/compiler/noirc_frontend/src/lib.rs index b05c635f436..b14f65a3e35 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/lib.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/lib.rs @@ -15,6 +15,7 @@ pub mod debug; pub mod elaborator; pub mod graph; pub mod lexer; +pub mod locations; pub mod monomorphization; pub mod node_interner; pub mod parser; diff --git a/noir/noir-repo/compiler/noirc_frontend/src/locations.rs b/noir/noir-repo/compiler/noirc_frontend/src/locations.rs new file mode 100644 index 00000000000..dd6a3412a40 --- /dev/null +++ b/noir/noir-repo/compiler/noirc_frontend/src/locations.rs @@ -0,0 +1,122 @@ +use fm::FileId; +use noirc_errors::Location; +use rangemap::RangeMap; +use rustc_hash::FxHashMap; + +use crate::{macros_api::NodeInterner, node_interner::DependencyId}; +use petgraph::prelude::NodeIndex as PetGraphIndex; + +#[derive(Debug, Default)] +pub(crate) struct LocationIndices { + map_file_to_range: FxHashMap>, +} + +impl LocationIndices { + pub(crate) fn add_location(&mut self, location: Location, node_index: PetGraphIndex) { + // Some location spans are empty: maybe they are from ficticious nodes? + if location.span.start() == location.span.end() { + return; + } + + let range_map = self.map_file_to_range.entry(location.file).or_default(); + range_map.insert(location.span.start()..location.span.end(), node_index); + } + + pub(crate) fn get_node_from_location(&self, location: Location) -> Option { + let range_map = self.map_file_to_range.get(&location.file)?; + Some(*range_map.get(&location.span.start())?) + } +} + +impl NodeInterner { + pub fn dependency_location(&self, dependency: DependencyId) -> Location { + match dependency { + DependencyId::Function(id) => self.function_modifiers(&id).name_location, + DependencyId::Struct(id) => self.get_struct(id).borrow().location, + DependencyId::Global(id) => self.get_global(id).location, + DependencyId::Alias(id) => self.get_type_alias(id).borrow().location, + DependencyId::Variable(location) => location, + } + } + + pub(crate) fn add_reference(&mut self, referenced: DependencyId, reference: DependencyId) { + let referenced_index = self.get_or_insert_reference(referenced); + let reference_index = self.reference_graph.add_node(reference); + + let referenced_location = self.dependency_location(referenced); + let reference_location = self.dependency_location(reference); + + self.reference_graph.add_edge(referenced_index, reference_index, ()); + self.location_indices.add_location(referenced_location, referenced_index); + self.location_indices.add_location(reference_location, reference_index); + } + + pub(crate) fn add_reference_for( + &mut self, + referenced_id: DependencyId, + reference: DependencyId, + ) { + let Some(referenced_index) = self.reference_graph_indices.get(&referenced_id) else { + panic!("Compiler Error: Referenced index not found") + }; + + let reference_location = self.dependency_location(reference); + let reference_index = self.reference_graph.add_node(reference); + self.reference_graph.add_edge(*referenced_index, reference_index, ()); + self.location_indices.add_location(reference_location, reference_index); + } + + pub(crate) fn add_definition_location(&mut self, referenced: DependencyId) { + let referenced_index = self.get_or_insert_reference(referenced); + let referenced_location = self.dependency_location(referenced); + self.location_indices.add_location(referenced_location, referenced_index); + } + + #[tracing::instrument(skip(self), ret)] + pub(crate) fn get_or_insert_reference(&mut self, id: DependencyId) -> PetGraphIndex { + if let Some(index) = self.reference_graph_indices.get(&id) { + return *index; + } + + let index = self.reference_graph.add_node(id); + self.reference_graph_indices.insert(id, index); + index + } + + pub fn check_rename_possible(&self, location: Location) -> bool { + self.location_indices.get_node_from_location(location).is_some() + } + + pub fn find_rename_symbols_at(&self, location: Location) -> Option> { + let node_index = self.location_indices.get_node_from_location(location)?; + + let reference_node = self.reference_graph[node_index]; + let found_locations: Vec = match reference_node { + DependencyId::Alias(_) | DependencyId::Struct(_) | DependencyId::Global(_) => todo!(), + DependencyId::Function(_) => self.get_edit_locations(node_index), + + DependencyId::Variable(_) => { + let referenced_node_index = self + .reference_graph + .neighbors_directed(node_index, petgraph::Direction::Incoming) + .next()?; + + self.get_edit_locations(referenced_node_index) + } + }; + Some(found_locations) + } + + fn get_edit_locations(&self, referenced_node_index: PetGraphIndex) -> Vec { + let id = self.reference_graph[referenced_node_index]; + let mut edit_locations = vec![self.dependency_location(id)]; + + self.reference_graph + .neighbors_directed(referenced_node_index, petgraph::Direction::Outgoing) + .for_each(|reference_node_index| { + let id = self.reference_graph[reference_node_index]; + edit_locations.push(self.dependency_location(id)); + }); + edit_locations + } +} 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 ebf0503963e..071ca95b114 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/monomorphization/mod.rs @@ -9,6 +9,9 @@ //! The entry point to this pass is the `monomorphize` function which, starting from a given //! function, will monomorphize the entire reachable program. use crate::ast::{FunctionKind, IntegerBitSize, Signedness, UnaryOp, Visibility}; +use crate::hir::comptime::InterpreterError; +use crate::hir::type_check::NoMatchingImplFoundError; +use crate::node_interner::ExprId; use crate::{ debug::DebugInstrumenter, hir_def::{ @@ -125,7 +128,7 @@ pub fn monomorphize_debug( monomorphizer.locals.clear(); perform_instantiation_bindings(&bindings); - let impl_bindings = monomorphizer.perform_impl_bindings(trait_method, next_fn_id); + let impl_bindings = perform_impl_bindings(monomorphizer.interner, trait_method, next_fn_id); monomorphizer.function(next_fn_id, new_id)?; undo_instantiation_bindings(impl_bindings); undo_instantiation_bindings(bindings); @@ -467,23 +470,11 @@ impl<'interner> Monomorphizer<'interner> { if self.interner.get_selected_impl_for_expression(expr).is_some() { // If an impl was selected for this infix operator, replace it // with a method call to the appropriate trait impl method. - let lhs_type = self.interner.id_type(infix.lhs); - let args = vec![lhs_type.clone(), lhs_type]; - - // If this is a comparison operator, the result is a boolean but - // the actual method call returns an Ordering - use crate::ast::BinaryOpKind::*; - let ret = if matches!(operator, Less | LessEqual | Greater | GreaterEqual) { - self.interner.ordering_type() - } else { - self.interner.id_type(expr) - }; - - let env = Box::new(Type::Unit); - let function_type = Type::Function(args, Box::new(ret.clone()), env); + let (function_type, ret) = + self.interner.get_operator_type(infix.lhs, operator, expr); let method = infix.trait_method_id; - let func = self.resolve_trait_method_reference(expr, function_type, method)?; + let func = self.resolve_trait_method_expr(expr, function_type, method)?; self.create_operator_impl_call(func, lhs, infix.operator, rhs, ret, location)? } else { let lhs = Box::new(lhs); @@ -843,7 +834,7 @@ impl<'interner> Monomorphizer<'interner> { let typ = self.interner.id_type(expr_id); if let ImplKind::TraitMethod(method, _, _) = ident.impl_kind { - return self.resolve_trait_method_reference(expr_id, typ, method); + return self.resolve_trait_method_expr(expr_id, typ, method); } let definition = self.interner.definition(ident.id); @@ -1046,53 +1037,14 @@ impl<'interner> Monomorphizer<'interner> { } } - fn resolve_trait_method_reference( + fn resolve_trait_method_expr( &mut self, expr_id: node_interner::ExprId, function_type: HirType, method: TraitMethodId, ) -> Result { - let trait_impl = self - .interner - .get_selected_impl_for_expression(expr_id) - .expect("ICE: missing trait impl - should be caught during type checking"); - - let func_id = match trait_impl { - node_interner::TraitImplKind::Normal(impl_id) => { - self.interner.get_trait_implementation(impl_id).borrow().methods - [method.method_index] - } - node_interner::TraitImplKind::Assumed { object_type, trait_generics } => { - match self.interner.lookup_trait_implementation( - &object_type, - method.trait_id, - &trait_generics, - ) { - Ok(TraitImplKind::Normal(impl_id)) => { - self.interner.get_trait_implementation(impl_id).borrow().methods - [method.method_index] - } - Ok(TraitImplKind::Assumed { .. }) => unreachable!( - "There should be no remaining Assumed impls during monomorphization" - ), - Err(constraints) => { - let failed_constraints = vecmap(constraints, |constraint| { - let id = constraint.trait_id; - let mut name = self.interner.get_trait(id).name.to_string(); - if !constraint.trait_generics.is_empty() { - let types = - vecmap(&constraint.trait_generics, |t| format!("{t:?}")); - name += &format!("<{}>", types.join(", ")); - } - format!(" {}: {name}", constraint.typ) - }) - .join("\n"); - - unreachable!("Failed to find trait impl during monomorphization. The failed constraint(s) are:\n{failed_constraints}") - } - } - } - }; + let func_id = resolve_trait_method(self.interner, method, expr_id) + .map_err(MonomorphizationError::InterpreterError)?; let func_id = match self.lookup_function(func_id, expr_id, &function_type, vec![], Some(method)) { @@ -1763,46 +1715,6 @@ impl<'interner> Monomorphizer<'interner> { Ok(result) } - - /// Call sites are instantiated against the trait method, but when an impl is later selected, - /// the corresponding method in the impl will have a different set of generics. `perform_impl_bindings` - /// is needed to apply the generics from the trait method to the impl method. Without this, - /// static method references to generic impls (e.g. `Eq::eq` for `[T; N]`) will fail to re-apply - /// the correct type bindings during monomorphization. - fn perform_impl_bindings( - &self, - trait_method: Option, - impl_method: node_interner::FuncId, - ) -> TypeBindings { - let mut bindings = TypeBindings::new(); - - if let Some(trait_method) = trait_method { - let the_trait = self.interner.get_trait(trait_method.trait_id); - - let trait_method_type = the_trait.methods[trait_method.method_index].typ.as_monotype(); - - // Make each NamedGeneric in this type bindable by replacing it with a TypeVariable - // with the same internal id and binding. - let (generics, impl_method_type) = - self.interner.function_meta(&impl_method).typ.unwrap_forall(); - - let replace_type_variable = |var: &TypeVariable| { - (var.id(), (var.clone(), Type::TypeVariable(var.clone(), TypeVariableKind::Normal))) - }; - - // Replace each NamedGeneric with a TypeVariable containing the same internal type variable - let type_bindings = generics.iter().map(replace_type_variable).collect(); - let impl_method_type = impl_method_type.force_substitute(&type_bindings); - - trait_method_type.try_unify(&impl_method_type, &mut bindings).unwrap_or_else(|_| { - unreachable!("Impl method type {} does not unify with trait method type {} during monomorphization", impl_method_type, trait_method_type) - }); - - perform_instantiation_bindings(&bindings); - } - - bindings - } } fn unwrap_tuple_type(typ: &HirType) -> Vec { @@ -1830,3 +1742,84 @@ pub fn undo_instantiation_bindings(bindings: TypeBindings) { var.unbind(id); } } + +/// Call sites are instantiated against the trait method, but when an impl is later selected, +/// the corresponding method in the impl will have a different set of generics. `perform_impl_bindings` +/// is needed to apply the generics from the trait method to the impl method. Without this, +/// static method references to generic impls (e.g. `Eq::eq` for `[T; N]`) will fail to re-apply +/// the correct type bindings during monomorphization. +pub fn perform_impl_bindings( + interner: &NodeInterner, + trait_method: Option, + impl_method: node_interner::FuncId, +) -> TypeBindings { + let mut bindings = TypeBindings::new(); + + if let Some(trait_method) = trait_method { + let the_trait = interner.get_trait(trait_method.trait_id); + + let trait_method_type = the_trait.methods[trait_method.method_index].typ.as_monotype(); + + // Make each NamedGeneric in this type bindable by replacing it with a TypeVariable + // with the same internal id and binding. + let (generics, impl_method_type) = interner.function_meta(&impl_method).typ.unwrap_forall(); + + let replace_type_variable = |var: &TypeVariable| { + (var.id(), (var.clone(), Type::TypeVariable(var.clone(), TypeVariableKind::Normal))) + }; + + // Replace each NamedGeneric with a TypeVariable containing the same internal type variable + let type_bindings = generics.iter().map(replace_type_variable).collect(); + let impl_method_type = impl_method_type.force_substitute(&type_bindings); + + trait_method_type.try_unify(&impl_method_type, &mut bindings).unwrap_or_else(|_| { + unreachable!("Impl method type {} does not unify with trait method type {} during monomorphization", impl_method_type, trait_method_type) + }); + + perform_instantiation_bindings(&bindings); + } + + bindings +} + +pub fn resolve_trait_method( + interner: &NodeInterner, + method: TraitMethodId, + expr_id: ExprId, +) -> Result { + let trait_impl = interner.get_selected_impl_for_expression(expr_id).ok_or_else(|| { + let location = interner.expr_location(&expr_id); + InterpreterError::NoImpl { location } + })?; + + let impl_id = match trait_impl { + TraitImplKind::Normal(impl_id) => impl_id, + TraitImplKind::Assumed { object_type, trait_generics } => { + match interner.lookup_trait_implementation( + &object_type, + method.trait_id, + &trait_generics, + ) { + Ok(TraitImplKind::Normal(impl_id)) => impl_id, + Ok(TraitImplKind::Assumed { .. }) => { + let location = interner.expr_location(&expr_id); + return Err(InterpreterError::NoImpl { location }); + } + Err(constraints) => { + let location = interner.expr_location(&expr_id); + if let Some(error) = + NoMatchingImplFoundError::new(interner, constraints, location.span) + { + let file = location.file; + return Err(InterpreterError::NoMatchingImplFound { error, file }); + } else { + let location = interner.expr_location(&expr_id); + return Err(InterpreterError::NoImpl { location }); + } + } + } + } + }; + + Ok(interner.get_trait_implementation(impl_id).borrow().methods[method.method_index]) +} diff --git a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs index 17531d09eac..2cb18a71d7a 100644 --- a/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs +++ b/noir/noir-repo/compiler/noirc_frontend/src/node_interner.rs @@ -31,6 +31,7 @@ use crate::hir_def::{ function::{FuncMeta, HirFunction}, stmt::HirStatement, }; +use crate::locations::LocationIndices; use crate::token::{Attributes, SecondaryAttribute}; use crate::GenericTypeVars; use crate::Generics; @@ -64,7 +65,7 @@ pub struct NodeInterner { function_modules: HashMap, /// This graph tracks dependencies between different global definitions. - /// This is used to ensure the absense of dependency cycles for globals and types. + /// This is used to ensure the absence of dependency cycles for globals and types. dependency_graph: DiGraph, /// To keep track of where each DependencyId is in `dependency_graph`, we need @@ -182,6 +183,15 @@ pub struct NodeInterner { /// and creating a `Token::QuotedType(id)` from this id. We cannot create a token holding /// the actual type since types do not implement Send or Sync. quoted_types: noirc_arena::Arena, + + /// Store the location of the references in the graph + pub(crate) reference_graph: DiGraph, + + /// Tracks the index of the references in the graph + pub(crate) reference_graph_indices: HashMap, + + /// Store the location of the references in the graph + pub(crate) location_indices: LocationIndices, } /// A dependency in the dependency graph may be a type or a definition. @@ -200,6 +210,7 @@ pub enum DependencyId { Global(GlobalId), Function(FuncId), Alias(TypeAliasId), + Variable(Location), } /// A trait implementation is either a normal implementation that is present in the source @@ -258,6 +269,9 @@ pub struct FunctionModifiers { pub generic_count: usize, pub is_comptime: bool, + + /// The location of the function's name rather than the entire function + pub name_location: Location, } impl FunctionModifiers { @@ -272,6 +286,7 @@ impl FunctionModifiers { is_unconstrained: false, generic_count: 0, is_comptime: false, + name_location: Location::dummy(), } } } @@ -516,6 +531,9 @@ impl Default for NodeInterner { type_alias_ref: Vec::new(), type_ref_locations: Vec::new(), quoted_types: Default::default(), + location_indices: LocationIndices::default(), + reference_graph: petgraph::graph::DiGraph::new(), + reference_graph_indices: HashMap::new(), }; // An empty block expression is used often, we add this into the `node` on startup @@ -804,8 +822,14 @@ impl NodeInterner { is_unconstrained: function.is_unconstrained, generic_count: function.generics.len(), is_comptime: function.is_comptime, + name_location: Location::new(function.name.span(), location.file), }; - self.push_function_definition(id, modifiers, module, location) + let definition_id = self.push_function_definition(id, modifiers, module, location); + + // This needs to be done after pushing the definition since it will reference the + // location that was stored + self.add_definition_location(DependencyId::Function(id)); + definition_id } pub fn push_function_definition( @@ -1194,6 +1218,17 @@ impl NodeInterner { self.trait_implementations[&id].clone() } + /// If the given function belongs to a trait impl, return its trait method id. + /// Otherwise, return None. + pub fn get_trait_method_id(&self, function: FuncId) -> Option { + let impl_id = self.function_meta(&function).trait_impl?; + let trait_impl = self.get_trait_implementation(impl_id); + let trait_impl = trait_impl.borrow(); + + let method_index = trait_impl.methods.iter().position(|id| *id == function)?; + Some(TraitMethodId { trait_id: trait_impl.trait_id, method_index }) + } + /// Given a `ObjectType: TraitId` pair, try to find an existing impl that satisfies the /// constraint. If an impl cannot be found, this will return a vector of each constraint /// in the path to get to the failing constraint. Usually this is just the single failing @@ -1664,13 +1699,13 @@ impl NodeInterner { self.add_dependency(dependent, DependencyId::Alias(dependency)); } - fn add_dependency(&mut self, dependent: DependencyId, dependency: DependencyId) { + pub fn add_dependency(&mut self, dependent: DependencyId, dependency: DependencyId) { let dependent_index = self.get_or_insert_dependency(dependent); let dependency_index = self.get_or_insert_dependency(dependency); self.dependency_graph.update_edge(dependent_index, dependency_index, ()); } - fn get_or_insert_dependency(&mut self, id: DependencyId) -> PetGraphIndex { + pub fn get_or_insert_dependency(&mut self, id: DependencyId) -> PetGraphIndex { if let Some(index) = self.dependency_graph_indices.get(&id) { return *index; } @@ -1721,6 +1756,11 @@ impl NodeInterner { } // Mutually recursive functions are allowed DependencyId::Function(_) => (), + // Local variables should never be in a dependency cycle, scoping rules + // prevents referring to them before they're defined + DependencyId::Variable(loc) => unreachable!( + "Variable used at location {loc:?} caught in a dependency cycle" + ), } } } @@ -1742,6 +1782,9 @@ impl NodeInterner { DependencyId::Global(id) => { Cow::Borrowed(self.get_global(id).ident.0.contents.as_ref()) } + DependencyId::Variable(loc) => { + unreachable!("Variable used at location {loc:?} caught in a dependency cycle") + } }; let mut cycle = index_to_string(scc[start_index]).to_string(); @@ -1762,6 +1805,29 @@ impl NodeInterner { pub fn get_quoted_type(&self, id: QuotedTypeId) -> &Type { &self.quoted_types[id.0] } + + /// Returns the type of an operator (which is always a function), along with its return type. + pub fn get_operator_type( + &self, + lhs: ExprId, + operator: BinaryOpKind, + operator_expr: ExprId, + ) -> (Type, Type) { + let lhs_type = self.id_type(lhs); + let args = vec![lhs_type.clone(), lhs_type]; + + // If this is a comparison operator, the result is a boolean but + // the actual method call returns an Ordering + use crate::ast::BinaryOpKind::*; + let ret = if matches!(operator, Less | LessEqual | Greater | GreaterEqual) { + self.ordering_type() + } else { + self.id_type(operator_expr) + }; + + let env = Box::new(Type::Unit); + (Type::Function(args, Box::new(ret.clone()), env), ret) + } } impl Methods { diff --git a/noir/noir-repo/cspell.json b/noir/noir-repo/cspell.json index 2fb20ae2ba4..b3a39108f24 100644 --- a/noir/noir-repo/cspell.json +++ b/noir/noir-repo/cspell.json @@ -150,6 +150,7 @@ "nouner", "pedersen", "peekable", + "petgraph", "plonkc", "PLONKish", "pprof", @@ -161,6 +162,7 @@ "pseudocode", "pubkey", "quantile", + "rangemap", "repr", "reqwest", "rfind", @@ -185,6 +187,7 @@ "subtyping", "swcurve", "Taiko", + "tarjan", "tecurve", "tempdir", "tempfile", @@ -203,6 +206,7 @@ "urem", "USERPROFILE", "vecmap", + "vitkov", "wasi", "wasmer", "Weierstraß", diff --git a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/ec_primitives.md b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/ec_primitives.md index f839b4a228e..f262d8160d6 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/ec_primitives.md +++ b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/ec_primitives.md @@ -18,7 +18,7 @@ curve you want to use, which would be specified using any one of the methods `std::ec::{tecurve,montcurve,swcurve}::{affine,curvegroup}::new` which take the coefficients in the defining equation together with a generator point as parameters. You can find more detail in the comments in -[`noir_stdlib/src/ec.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr), but +[`noir_stdlib/src/ec/mod.nr`](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec/mod.nr), but the gist of it is that the elliptic curves of interest are usually expressed in one of the standard forms implemented here (Twisted Edwards, Montgomery and Short Weierstraß), and in addition to that, you could choose to use `affine` coordinates (Cartesian coordinates - the usual (x,y) - possibly @@ -67,7 +67,7 @@ does indeed lie on `c` by calling `c.contains(p1)`. the curve configurations, the SWU map-to-curve method may be called as `c.swu_map(z,n)`, where `z: Field` depends on `Field` and `c` and must be chosen by the user (the conditions it needs to satisfy are specified in the comments - [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec.nr)). + [here](https://github.com/noir-lang/noir/blob/master/noir_stdlib/src/ec/mod.nr)). ## Examples diff --git a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx index efa52b2c3f2..05a2bb983a1 100644 --- a/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx +++ b/noir/noir-repo/docs/docs/noir/standard_library/cryptographic_primitives/hashes.mdx @@ -15,7 +15,7 @@ import BlackBoxInfo from '@site/src/components/Notes/_blackbox.mdx'; Given an array of bytes, returns the resulting sha256 hash. Specify a message_size to hash only the first `message_size` bytes of the input. -#include_code sha256 noir_stdlib/src/hash.nr rust +#include_code sha256 noir_stdlib/src/hash/mod.nr rust example: #include_code sha256_var test_programs/execution_success/sha256/src/main.nr rust @@ -34,7 +34,7 @@ fn main() { Given an array of bytes, returns an array with the Blake2 hash -#include_code blake2s noir_stdlib/src/hash.nr rust +#include_code blake2s noir_stdlib/src/hash/mod.nr rust example: @@ -51,7 +51,7 @@ fn main() { Given an array of bytes, returns an array with the Blake3 hash -#include_code blake3 noir_stdlib/src/hash.nr rust +#include_code blake3 noir_stdlib/src/hash/mod.nr rust example: @@ -68,7 +68,7 @@ fn main() { Given an array of Fields, returns the Pedersen hash. -#include_code pedersen_hash noir_stdlib/src/hash.nr rust +#include_code pedersen_hash noir_stdlib/src/hash/mod.nr rust example: @@ -80,7 +80,7 @@ example: Given an array of Fields, returns the Pedersen commitment. -#include_code pedersen_commitment noir_stdlib/src/hash.nr rust +#include_code pedersen_commitment noir_stdlib/src/hash/mod.nr rust example: @@ -94,7 +94,7 @@ Given an array of bytes (`u8`), returns the resulting keccak hash as an array of 32 bytes (`[u8; 32]`). Specify a message_size to hash only the first `message_size` bytes of the input. -#include_code keccak256 noir_stdlib/src/hash.nr rust +#include_code keccak256 noir_stdlib/src/hash/mod.nr rust example: diff --git a/noir/noir-repo/noir_stdlib/src/collections.nr b/noir/noir-repo/noir_stdlib/src/collections/mod.nr similarity index 100% rename from noir/noir-repo/noir_stdlib/src/collections.nr rename to noir/noir-repo/noir_stdlib/src/collections/mod.nr diff --git a/noir/noir-repo/noir_stdlib/src/ec/consts.nr b/noir/noir-repo/noir_stdlib/src/ec/consts/mod.nr similarity index 100% rename from noir/noir-repo/noir_stdlib/src/ec/consts.nr rename to noir/noir-repo/noir_stdlib/src/ec/consts/mod.nr diff --git a/noir/noir-repo/noir_stdlib/src/ec.nr b/noir/noir-repo/noir_stdlib/src/ec/mod.nr similarity index 100% rename from noir/noir-repo/noir_stdlib/src/ec.nr rename to noir/noir-repo/noir_stdlib/src/ec/mod.nr diff --git a/noir/noir-repo/noir_stdlib/src/field.nr b/noir/noir-repo/noir_stdlib/src/field/mod.nr similarity index 100% rename from noir/noir-repo/noir_stdlib/src/field.nr rename to noir/noir-repo/noir_stdlib/src/field/mod.nr diff --git a/noir/noir-repo/noir_stdlib/src/hash.nr b/noir/noir-repo/noir_stdlib/src/hash/mod.nr similarity index 100% rename from noir/noir-repo/noir_stdlib/src/hash.nr rename to noir/noir-repo/noir_stdlib/src/hash/mod.nr diff --git a/noir/noir-repo/noir_stdlib/src/hash/poseidon.nr b/noir/noir-repo/noir_stdlib/src/hash/poseidon/mod.nr similarity index 100% rename from noir/noir-repo/noir_stdlib/src/hash/poseidon.nr rename to noir/noir-repo/noir_stdlib/src/hash/poseidon/mod.nr diff --git a/noir/noir-repo/noir_stdlib/src/meta.nr b/noir/noir-repo/noir_stdlib/src/meta/mod.nr similarity index 100% rename from noir/noir-repo/noir_stdlib/src/meta.nr rename to noir/noir-repo/noir_stdlib/src/meta/mod.nr diff --git a/noir/noir-repo/noir_stdlib/src/ops.nr b/noir/noir-repo/noir_stdlib/src/ops/mod.nr similarity index 100% rename from noir/noir-repo/noir_stdlib/src/ops.nr rename to noir/noir-repo/noir_stdlib/src/ops/mod.nr diff --git a/noir/noir-repo/test_programs/compile_success_empty/comptime_traits/Nargo.toml b/noir/noir-repo/test_programs/compile_success_empty/comptime_traits/Nargo.toml new file mode 100644 index 00000000000..75df4dc5c20 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/comptime_traits/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "comptime_traits" +type = "bin" +authors = [""] +compiler_version = ">=0.31.0" + +[dependencies] diff --git a/noir/noir-repo/test_programs/compile_success_empty/comptime_traits/src/main.nr b/noir/noir-repo/test_programs/compile_success_empty/comptime_traits/src/main.nr new file mode 100644 index 00000000000..143c9cda274 --- /dev/null +++ b/noir/noir-repo/test_programs/compile_success_empty/comptime_traits/src/main.nr @@ -0,0 +1,15 @@ +fn main() { + comptime + { + // impl Eq for Field + assert(3 == 3); + + // impl Default for [T; N] where T: Default + // impl Default for Field + let array = Default::default(); + + // impl Eq for [T; N] where T: Eq + // impl Eq for Field + assert([1, 2] != array); + } +} diff --git a/noir/noir-repo/tooling/lsp/src/lib.rs b/noir/noir-repo/tooling/lsp/src/lib.rs index 304a2d34e47..92924e701a6 100644 --- a/noir/noir-repo/tooling/lsp/src/lib.rs +++ b/noir/noir-repo/tooling/lsp/src/lib.rs @@ -20,7 +20,10 @@ use async_lsp::{ }; use fm::{codespan_files as files, FileManager}; use fxhash::FxHashSet; -use lsp_types::CodeLens; +use lsp_types::{ + request::{PrepareRenameRequest, Rename}, + CodeLens, +}; use nargo::{ package::{Package, PackageType}, parse_all, @@ -43,8 +46,8 @@ use notifications::{ }; use requests::{ on_code_lens_request, on_formatting, on_goto_declaration_request, on_goto_definition_request, - on_goto_type_definition_request, on_initialize, on_profile_run_request, on_shutdown, - on_test_run_request, on_tests_request, + on_goto_type_definition_request, on_initialize, on_prepare_rename_request, + on_profile_run_request, on_rename_request, on_shutdown, on_test_run_request, on_tests_request, }; use serde_json::Value as JsonValue; use thiserror::Error; @@ -55,6 +58,9 @@ mod requests; mod solver; mod types; +#[cfg(test)] +mod test_utils; + use solver::WrapperSolver; use types::{notification, request, NargoTest, NargoTestId, Position, Range, Url}; @@ -119,6 +125,8 @@ impl NargoLspService { .request::(on_goto_definition_request) .request::(on_goto_declaration_request) .request::(on_goto_type_definition_request) + .request::(on_prepare_rename_request) + .request::(on_rename_request) .notification::(on_initialized) .notification::(on_did_change_configuration) .notification::(on_did_open_text_document) diff --git a/noir/noir-repo/tooling/lsp/src/requests/goto_definition.rs b/noir/noir-repo/tooling/lsp/src/requests/goto_definition.rs index 3a92e28cc11..4985c565e06 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/goto_definition.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/goto_definition.rs @@ -76,59 +76,42 @@ fn on_goto_definition_inner( #[cfg(test)] mod goto_definition_tests { + use std::panic; - use acvm::blackbox_solver::StubbedBlackBoxSolver; - use async_lsp::ClientSocket; - use lsp_types::{Position, Url}; + use crate::test_utils; + use lsp_types::{Position, Range}; use tokio::test; use super::*; #[test] async fn test_on_goto_definition() { - let client = ClientSocket::new_closed(); - let mut state = LspState::new(&client, StubbedBlackBoxSolver); - - let root_path = std::env::current_dir() - .unwrap() - .join("../../test_programs/execution_success/7_function") - .canonicalize() - .expect("Could not resolve root path"); - let noir_text_document = Url::from_file_path(root_path.join("src/main.nr").as_path()) - .expect("Could not convert text document path to URI"); - let root_uri = Some( - Url::from_file_path(root_path.as_path()).expect("Could not convert root path to URI"), - ); - - #[allow(deprecated)] - let initialize_params = lsp_types::InitializeParams { - process_id: Default::default(), - root_path: None, - root_uri, - initialization_options: None, - capabilities: Default::default(), - trace: Some(lsp_types::TraceValue::Verbose), - workspace_folders: None, - client_info: None, - locale: None, - }; - let _initialize_response = crate::requests::on_initialize(&mut state, initialize_params) - .await - .expect("Could not initialize LSP server"); + let (mut state, noir_text_document) = test_utils::init_lsp_server("go_to_definition").await; let params = GotoDefinitionParams { text_document_position_params: lsp_types::TextDocumentPositionParams { text_document: lsp_types::TextDocumentIdentifier { uri: noir_text_document }, - position: Position { line: 95, character: 5 }, + position: Position { line: 9, character: 12 }, // Right at the beginning of "another_function" }, work_done_progress_params: Default::default(), partial_result_params: Default::default(), }; - let response = on_goto_definition_request(&mut state, params) + let response: GotoDefinitionResponse = on_goto_definition_request(&mut state, params) .await - .expect("Could execute on_goto_definition_request"); - - assert!(&response.is_some()); + .expect("Could execute on_goto_definition_request") + .expect("Didn't get a goto definition response"); + + if let GotoDefinitionResponse::Scalar(location) = response { + assert_eq!( + location.range, + Range { + start: Position { line: 4, character: 3 }, + end: Position { line: 4, character: 19 }, + } + ); + } else { + panic!("Expected a scalar response"); + }; } } diff --git a/noir/noir-repo/tooling/lsp/src/requests/mod.rs b/noir/noir-repo/tooling/lsp/src/requests/mod.rs index 769e9ba17ce..545b5fef3d2 100644 --- a/noir/noir-repo/tooling/lsp/src/requests/mod.rs +++ b/noir/noir-repo/tooling/lsp/src/requests/mod.rs @@ -5,7 +5,7 @@ use async_lsp::{ErrorCode, ResponseError}; use fm::{codespan_files::Error, FileMap, PathString}; use lsp_types::{ DeclarationCapability, Location, Position, TextDocumentSyncCapability, TextDocumentSyncKind, - TypeDefinitionProviderCapability, Url, + TypeDefinitionProviderCapability, Url, WorkDoneProgressOptions, }; use nargo_fmt::Config; use serde::{Deserialize, Serialize}; @@ -29,6 +29,7 @@ mod code_lens_request; mod goto_declaration; mod goto_definition; mod profile_run; +mod rename; mod test_run; mod tests; @@ -36,7 +37,8 @@ pub(crate) use { code_lens_request::collect_lenses_for_package, code_lens_request::on_code_lens_request, goto_declaration::on_goto_declaration_request, goto_definition::on_goto_definition_request, goto_definition::on_goto_type_definition_request, profile_run::on_profile_run_request, - test_run::on_test_run_request, tests::on_tests_request, + rename::on_prepare_rename_request, rename::on_rename_request, test_run::on_test_run_request, + tests::on_tests_request, }; /// LSP client will send initialization request after the server has started. @@ -106,6 +108,12 @@ pub(crate) fn on_initialize( definition_provider: Some(lsp_types::OneOf::Left(true)), declaration_provider: Some(DeclarationCapability::Simple(true)), type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)), + rename_provider: Some(lsp_types::OneOf::Right(lsp_types::RenameOptions { + prepare_provider: Some(true), + work_done_progress_options: WorkDoneProgressOptions { + work_done_progress: None, + }, + })), }, server_info: None, }) diff --git a/noir/noir-repo/tooling/lsp/src/requests/rename.rs b/noir/noir-repo/tooling/lsp/src/requests/rename.rs new file mode 100644 index 00000000000..9f6416a2c63 --- /dev/null +++ b/noir/noir-repo/tooling/lsp/src/requests/rename.rs @@ -0,0 +1,249 @@ +use std::{ + collections::HashMap, + future::{self, Future}, +}; + +use async_lsp::{ErrorCode, ResponseError}; +use fm::FileMap; +use lsp_types::{ + PrepareRenameResponse, RenameParams, TextDocumentPositionParams, TextEdit, Url, WorkspaceEdit, +}; +use nargo::insert_all_files_for_workspace_into_file_manager; +use noirc_driver::file_manager_with_stdlib; +use noirc_errors::Location; +use noirc_frontend::macros_api::NodeInterner; + +use crate::{parse_diff, resolve_workspace_for_source_path, LspState}; + +use super::{position_to_byte_index, to_lsp_location}; + +pub(crate) fn on_prepare_rename_request( + state: &mut LspState, + params: TextDocumentPositionParams, +) -> impl Future, ResponseError>> { + let result = process_rename_request(state, params, |search_for_location, interner, _| { + let rename_possible = interner.check_rename_possible(search_for_location); + Some(PrepareRenameResponse::DefaultBehavior { default_behavior: rename_possible }) + }); + future::ready(result) +} + +pub(crate) fn on_rename_request( + state: &mut LspState, + params: RenameParams, +) -> impl Future, ResponseError>> { + let result = process_rename_request( + state, + params.text_document_position, + |search_for_location, interner, files| { + let rename_changes = + interner.find_rename_symbols_at(search_for_location).map(|locations| { + let rs = locations.iter().fold( + HashMap::new(), + |mut acc: HashMap>, location| { + let file_id = location.file; + let span = location.span; + + let Some(lsp_location) = to_lsp_location(files, file_id, span) else { + return acc; + }; + + let edit = TextEdit { + range: lsp_location.range, + new_text: params.new_name.clone(), + }; + + acc.entry(lsp_location.uri).or_default().push(edit); + + acc + }, + ); + rs + }); + + let response = WorkspaceEdit { + changes: rename_changes, + document_changes: None, + change_annotations: None, + }; + + Some(response) + }, + ); + future::ready(result) +} + +fn process_rename_request( + state: &mut LspState, + text_document_position_params: TextDocumentPositionParams, + callback: F, +) -> Result +where + F: FnOnce(Location, &NodeInterner, &FileMap) -> T, +{ + let file_path = + text_document_position_params.text_document.uri.to_file_path().map_err(|_| { + ResponseError::new(ErrorCode::REQUEST_FAILED, "URI is not a valid file path") + })?; + + let workspace = resolve_workspace_for_source_path(file_path.as_path()).unwrap(); + let package = workspace.members.first().unwrap(); + + let package_root_path: String = package.root_dir.as_os_str().to_string_lossy().into(); + + let mut workspace_file_manager = file_manager_with_stdlib(&workspace.root_dir); + insert_all_files_for_workspace_into_file_manager(&workspace, &mut workspace_file_manager); + let parsed_files = parse_diff(&workspace_file_manager, state); + + let (mut context, crate_id) = + nargo::prepare_package(&workspace_file_manager, &parsed_files, package); + + let interner; + if let Some(def_interner) = state.cached_definitions.get(&package_root_path) { + 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, false); + interner = &context.def_interner; + } + + let files = context.file_manager.as_file_map(); + let file_id = context.file_manager.name_to_id(file_path.clone()).ok_or(ResponseError::new( + ErrorCode::REQUEST_FAILED, + format!("Could not find file in file manager. File path: {:?}", file_path), + ))?; + let byte_index = + position_to_byte_index(files, file_id, &text_document_position_params.position).map_err( + |err| { + ResponseError::new( + ErrorCode::REQUEST_FAILED, + format!("Could not convert position to byte index. Error: {:?}", err), + ) + }, + )?; + + let search_for_location = noirc_errors::Location { + file: file_id, + span: noirc_errors::Span::single_char(byte_index as u32), + }; + + Ok(callback(search_for_location, interner, files)) +} + +#[cfg(test)] +mod rename_tests { + use super::*; + use crate::test_utils; + use lsp_types::{Position, Range, WorkDoneProgressParams}; + use tokio::test; + + async fn check_rename_succeeds(directory: &str, name: &str, ranges: &[Range]) { + let (mut state, noir_text_document) = test_utils::init_lsp_server(directory).await; + + let main_path = noir_text_document.path(); + + // As we process the rename requests we'll check that the request position actually + // includes the target name. + let file_contents = std::fs::read_to_string(main_path) + .unwrap_or_else(|_| panic!("Couldn't read file {}", main_path)); + + let file_lines: Vec<&str> = file_contents.lines().collect(); + + // Test renaming works on any instance of the symbol. + for target_range in ranges { + assert_eq!(target_range.start.line, target_range.end.line); + + // Check that the range includes the target name + let line = file_lines[target_range.start.line as usize]; + let chunk = + &line[target_range.start.character as usize..target_range.end.character as usize]; + assert_eq!(chunk, name); + + let target_position = target_range.start; + + let params = RenameParams { + text_document_position: TextDocumentPositionParams { + text_document: lsp_types::TextDocumentIdentifier { + uri: noir_text_document.clone(), + }, + position: target_position, + }, + new_name: "renamed_function".to_string(), + work_done_progress_params: WorkDoneProgressParams { work_done_token: None }, + }; + + let response = on_rename_request(&mut state, params) + .await + .expect("Could not execute on_prepare_rename_request") + .unwrap(); + + let changes = response.changes.expect("Expected to find rename changes"); + let mut changes: Vec = + changes.values().flatten().map(|edit| edit.range).collect(); + changes.sort_by_key(|range| range.start.line); + assert_eq!(changes, ranges); + } + } + + #[test] + async fn test_on_prepare_rename_request_cannot_be_applied() { + let (mut state, noir_text_document) = test_utils::init_lsp_server("rename").await; + + let params = TextDocumentPositionParams { + text_document: lsp_types::TextDocumentIdentifier { uri: noir_text_document }, + position: lsp_types::Position { line: 0, character: 0 }, // This is at the "f" of an "fn" keyword + }; + + let response = on_prepare_rename_request(&mut state, params) + .await + .expect("Could not execute on_prepare_rename_request"); + + assert_eq!( + response, + Some(PrepareRenameResponse::DefaultBehavior { default_behavior: false }) + ); + } + + #[test] + async fn test_on_rename_request() { + const ANOTHER_FUNCTION_REFERENCE: Range = Range { + start: Position { line: 9, character: 12 }, + end: Position { line: 9, character: 28 }, + }; + const ANOTHER_FUNCTION_DECLARATION: Range = Range { + start: Position { line: 4, character: 3 }, + end: Position { line: 4, character: 19 }, + }; + // The ranges of positions which represent the usage of the `another_function` symbol. + const ANOTHER_FUNCTION_RANGES: &[Range] = &[ + ANOTHER_FUNCTION_DECLARATION, + ANOTHER_FUNCTION_REFERENCE, + Range { + start: Position { line: 13, character: 12 }, + end: Position { line: 13, character: 28 }, + }, + Range { + start: Position { line: 19, character: 15 }, + end: Position { line: 19, character: 31 }, + }, + ]; + + check_rename_succeeds("rename", "another_function", ANOTHER_FUNCTION_RANGES).await; + } + + #[test] + async fn test_on_rename_request_works_with_qualified_path() { + const BAR_FUNCTION_REFERENCE: Range = Range { + start: Position { line: 1, character: 9 }, + end: Position { line: 1, character: 12 }, + }; + const BAR_FUNCTION_DECLARATION: Range = Range { + start: Position { line: 5, character: 11 }, + end: Position { line: 5, character: 14 }, + }; + // The ranges of positions which represent the usage of the `bar` symbol. + const BAR_FUNCTION_RANGES: &[Range] = &[BAR_FUNCTION_REFERENCE, BAR_FUNCTION_DECLARATION]; + + check_rename_succeeds("rename_qualified", "bar", BAR_FUNCTION_RANGES).await; + } +} diff --git a/noir/noir-repo/tooling/lsp/src/test_utils.rs b/noir/noir-repo/tooling/lsp/src/test_utils.rs new file mode 100644 index 00000000000..dcaec2fd615 --- /dev/null +++ b/noir/noir-repo/tooling/lsp/src/test_utils.rs @@ -0,0 +1,39 @@ +use crate::LspState; +use acvm::blackbox_solver::StubbedBlackBoxSolver; +use async_lsp::ClientSocket; +use lsp_types::Url; + +pub(crate) async fn init_lsp_server(directory: &str) -> (LspState, Url) { + let client = ClientSocket::new_closed(); + let mut state = LspState::new(&client, StubbedBlackBoxSolver); + + let root_path = std::env::current_dir() + .unwrap() + .join("test_programs") + .join(directory) + .canonicalize() + .expect("Could not resolve root path"); + let noir_text_document = Url::from_file_path(root_path.join("src/main.nr").as_path()) + .expect("Could not convert text document path to URI"); + let root_uri = + Some(Url::from_file_path(root_path.as_path()).expect("Could not convert root path to URI")); + + #[allow(deprecated)] + let initialize_params = lsp_types::InitializeParams { + process_id: Default::default(), + root_path: None, + root_uri, + initialization_options: None, + capabilities: Default::default(), + trace: Some(lsp_types::TraceValue::Verbose), + workspace_folders: None, + client_info: None, + locale: None, + }; + + let _initialize_response = crate::requests::on_initialize(&mut state, initialize_params) + .await + .expect("Could not initialize LSP server"); + + (state, noir_text_document) +} diff --git a/noir/noir-repo/tooling/lsp/src/types.rs b/noir/noir-repo/tooling/lsp/src/types.rs index e3492f21346..7239b1db685 100644 --- a/noir/noir-repo/tooling/lsp/src/types.rs +++ b/noir/noir-repo/tooling/lsp/src/types.rs @@ -1,6 +1,7 @@ use fm::FileId; use lsp_types::{ - DeclarationCapability, DefinitionOptions, OneOf, TypeDefinitionProviderCapability, + DeclarationCapability, DefinitionOptions, OneOf, RenameOptions, + TypeDefinitionProviderCapability, }; use noirc_driver::DebugFile; use noirc_errors::{debug_info::OpCodesCount, Location}; @@ -135,6 +136,10 @@ pub(crate) struct ServerCapabilities { /// The server handles and provides custom nargo messages. #[serde(skip_serializing_if = "Option::is_none")] pub(crate) nargo: Option, + + /// The server provides rename support. + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) rename_provider: Option>, } #[derive(Debug, PartialEq, Clone, Default, Deserialize, Serialize)] diff --git a/noir/noir-repo/tooling/lsp/test_programs/go_to_definition/Nargo.toml b/noir/noir-repo/tooling/lsp/test_programs/go_to_definition/Nargo.toml new file mode 100644 index 00000000000..c894a050c40 --- /dev/null +++ b/noir/noir-repo/tooling/lsp/test_programs/go_to_definition/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "go_to_definition" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/tooling/lsp/test_programs/go_to_definition/src/main.nr b/noir/noir-repo/tooling/lsp/test_programs/go_to_definition/src/main.nr new file mode 100644 index 00000000000..c27f8fed868 --- /dev/null +++ b/noir/noir-repo/tooling/lsp/test_programs/go_to_definition/src/main.nr @@ -0,0 +1,11 @@ +fn some_function() -> Field { + 1 + 2 +} + +fn another_function() -> Field { + 3 + 4 +} + +fn main() { + let _ = another_function(); +} diff --git a/noir/noir-repo/tooling/lsp/test_programs/rename/Nargo.toml b/noir/noir-repo/tooling/lsp/test_programs/rename/Nargo.toml new file mode 100644 index 00000000000..2d5b6415dc9 --- /dev/null +++ b/noir/noir-repo/tooling/lsp/test_programs/rename/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rename" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/tooling/lsp/test_programs/rename/src/main.nr b/noir/noir-repo/tooling/lsp/test_programs/rename/src/main.nr new file mode 100644 index 00000000000..4c28249582e --- /dev/null +++ b/noir/noir-repo/tooling/lsp/test_programs/rename/src/main.nr @@ -0,0 +1,22 @@ +fn some_function() -> Field { + 1 + 2 +} + +fn another_function() -> Field { + 3 + 4 +} + +fn main() { + let _ = another_function(); + + let _ = 1; + + let _ = another_function(); +} + + +mod foo { + fn yet_another_function() -> Field { + crate::another_function() + } +} \ No newline at end of file diff --git a/noir/noir-repo/tooling/lsp/test_programs/rename_qualified/Nargo.toml b/noir/noir-repo/tooling/lsp/test_programs/rename_qualified/Nargo.toml new file mode 100644 index 00000000000..7de13ef6b34 --- /dev/null +++ b/noir/noir-repo/tooling/lsp/test_programs/rename_qualified/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rename_qualified" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir/noir-repo/tooling/lsp/test_programs/rename_qualified/src/main.nr b/noir/noir-repo/tooling/lsp/test_programs/rename_qualified/src/main.nr new file mode 100644 index 00000000000..f1b77796210 --- /dev/null +++ b/noir/noir-repo/tooling/lsp/test_programs/rename_qualified/src/main.nr @@ -0,0 +1,9 @@ +fn main() -> pub Field { + foo::bar() +} + +mod foo { + pub fn bar() -> Field { + 1 + } +} diff --git a/noir/noir-repo/tooling/nargo_cli/build.rs b/noir/noir-repo/tooling/nargo_cli/build.rs index a6873910524..0fbdaaba0b4 100644 --- a/noir/noir-repo/tooling/nargo_cli/build.rs +++ b/noir/noir-repo/tooling/nargo_cli/build.rs @@ -61,12 +61,13 @@ const IGNORED_BRILLIG_TESTS: [&str; 11] = [ /// Certain features are only available in the elaborator. /// We skip these tests for non-elaborator code since they are not /// expected to work there. This can be removed once the old code is removed. -const IGNORED_NEW_FEATURE_TESTS: [&str; 5] = [ +const IGNORED_NEW_FEATURE_TESTS: [&str; 6] = [ "macros", "wildcard_type", "type_definition_annotation", "numeric_generics_explicit", "derive_impl", + "comptime_traits", ]; fn read_test_cases( diff --git a/noir/scripts/sync-in-fixup.sh b/noir/scripts/sync-in-fixup.sh index fce52060fa7..6820e62a800 100755 --- a/noir/scripts/sync-in-fixup.sh +++ b/noir/scripts/sync-in-fixup.sh @@ -18,4 +18,5 @@ sed -i "s/^require_command wasm-opt/#require_command wasm-opt/" ./tooling/noirc_ sed -i "s/^require_command wasm-opt/#require_command wasm-opt/" ./acvm-repo/acvm_js/build.sh # Replace `verify_honk_proof` test -cp -r ../verify_honk_proof ./test_programs/execution_success/verify_honk_proof +cp -r ../verify_honk_proof ./test_programs/execution_success/ +git add ./test_programs/execution_success/verify_honk_proof diff --git a/noir/verify_honk_proof/Prover.toml b/noir/verify_honk_proof/Prover.toml index af4e99197a5..921b69e100a 100644 --- a/noir/verify_honk_proof/Prover.toml +++ b/noir/verify_honk_proof/Prover.toml @@ -1,4 +1,4 @@ key_hash = "0x096129b1c6e108252fc5c829c4cc9b7e8f0d1fd9f29c2532b563d6396645e08f" proof = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000042ab5d6d1986846cf","0x00000000000000000000000000000000000000000000000b75c020998797da78","0x0000000000000000000000000000000000000000000000005a107acb64952eca","0x000000000000000000000000000000000000000000000000000031e97a575e9d","0x00000000000000000000000000000000000000000000000b5666547acf8bd5a4","0x00000000000000000000000000000000000000000000000c410db10a01750aeb","0x00000000000000000000000000000000000000000000000d722669117f9758a4","0x000000000000000000000000000000000000000000000000000178cbf4206471","0x000000000000000000000000000000000000000000000000e91b8a11e7842c38","0x000000000000000000000000000000000000000000000007fd51009034b3357f","0x000000000000000000000000000000000000000000000009889939f81e9c7402","0x0000000000000000000000000000000000000000000000000000f94656a2ca48","0x000000000000000000000000000000000000000000000006fb128b46c1ddb67f","0x0000000000000000000000000000000000000000000000093fe27776f50224bd","0x000000000000000000000000000000000000000000000004a0c80c0da527a081","0x0000000000000000000000000000000000000000000000000001b52c2020d746","0x0000000000000000000000000000005a9bae947e1e91af9e4033d8d6aa6ed632","0x000000000000000000000000000000000025e485e013446d4ac7981c88ba6ecc","0x000000000000000000000000000000ff1e0496e30ab24a63b32b2d1120b76e62","0x00000000000000000000000000000000001afe0a8a685d7cd85d1010e55d9d7c","0x000000000000000000000000000000b0804efd6573805f991458295f510a2004","0x00000000000000000000000000000000000c81a178016e2fe18605022d5a8b0e","0x000000000000000000000000000000eba51e76eb1cfff60a53a0092a3c3dea47","0x000000000000000000000000000000000022e7466247b533282f5936ac4e6c15","0x00000000000000000000000000000071b1d76edf770edff98f00ff4deec264cd","0x00000000000000000000000000000000001e48128e68794d8861fcbb2986a383","0x000000000000000000000000000000d3a2af4915ae6d86b097adc377fafda2d4","0x000000000000000000000000000000000006359de9ca452dab3a4f1f8d9c9d98","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x0000000000000000000000000000000d9d719a8b9f020ad3642d60fe704e696f","0x00000000000000000000000000000000000ddfdbbdefc4ac1580ed38e12cfa49","0x0000000000000000000000000000008289fe9754ce48cd01b7be96a861b5e157","0x00000000000000000000000000000000000ff3e0896bdea021253b3d360fa678","0x000000000000000000000000000000f968b227a358a305607f3efc933823d288","0x00000000000000000000000000000000000eaf8adb390375a76d95e918b65e08","0x000000000000000000000000000000bb34b4b447aae56f5e24f81c3acd6d547f","0x00000000000000000000000000000000002175d012746260ebcfe339a91a81e1","0x0000000000000000000000000000005b739ed2075f2b046062b8fc6a2d1e9863","0x00000000000000000000000000000000001285cd1030d338c0e1603b4da2c838","0x00000000000000000000000000000027447d6c281eb38b2b937af4a516d60c04","0x000000000000000000000000000000000019bc3d980465fbb4a656a74296fc58","0x000000000000000000000000000000b484788ace8f7df86dd5e325d2e9b12599","0x00000000000000000000000000000000000a2ca0d10eb7b767114ae230b728d3","0x000000000000000000000000000000c6dfc7092f16f95795e437664498b88d53","0x0000000000000000000000000000000000131067b4e4d95a4f6f8cf5c9b5450a","0x0f413f22eec51f2a02800e0cafaeec1d92d744fbbaef213c687b9edabd6985f5","0x21230f4ff26c80ffb5d037a9d1d26c3f955ca34cbeca4f54db6656b932967a0c","0x0521f877fe35535767f99597cc50effbd283dcae6812ee0a7620d796ccbfd642","0x202b01350a9cc5c20ec0f3eaada338c0a3b793811bd539418ffa3cc4302615e2","0x2d1214d9b0d41058ad4a172d9c0aecc5bdabe95e687c3465050c6b5396509be4","0x1113b344a151b0af091cb28d728b752ebb4865da6cd7ee68471b961ca5cf69b9","0x2aa66d0954bb83e17bd5c9928d3aa7a7df75d741d409f7c15ba596804ba643fb","0x2e26bc7a530771ef7a95d5360d537e41cf94d8a0942764ff09881c107f91a106","0x0f14f32b921bb63ad1df00adab7c82af58ea8aa7f353f14b281208d8c5fab504","0x13429515c0c53b6502bbcdf545defb3cb69a986c9263e070fcbb397391aae1a3","0x1f21cac5e2f262afc1006a21454cc6bcb018c44e53ad8ab61cebbac99e539176","0x2a9886a6ddc8a61b097c668cd362fc8acdee8dde74f7b1af192c3e060bb2948f","0x2d718181e408ead2e9bcd30a84ad1fccbaf8d48ab6d1820bad4933d284b503c4","0x2634c1aafc902f14508f34d3d7e9d485f42d1a4c95b5a1ef73711ed0d3c68d77","0x092ede9777e6472ce5ffd8c963d466006189e960e2c591d338dc8d4af1a057fb","0x1cba45b17fd24f1cb1b4ab7b83eee741f6c77ba70a497dc4de259eceb7d5ea26","0x246e887c7bf2e17f919b2393b6e9b00b33e8822d862544a775aac05cb7bff710","0x04c3f539fe8689971948afcb437f1ecbd444a5bddaca1c8a450348dcd8480047","0x20c6a423ae4fd58e8951aa378d02d77baf90508ceb48856db2319d70938b186e","0x1bcf8786b554b3316d8ebdbc9d006a4e5d4865aad512ffd404b7f83550d3d030","0x09ab038260518f0970564afcd6bf22e2abf6b1fa5e12a327bbf195b6ca5edd78","0x1024e32554746f89c195286ba6ccfc9765e5d14bbe8064bc6fdf22d16ec6b495","0x17706656f8dbd7e47bb257a6428f0cb7278ea02fa9e6ce431d7bcc9133fba9c7","0x25a3e8a33c15ef2a4dd16313a6049bf1d468b4cdc141f238f2d51a1e8e1c22b3","0x1198863f08006edb27aee23164fb117a4ddec1bf1ed89807aa907e5cd24bf068","0x1862b4856b5b4d4a064f873e221703e4e2cd1ebfca1337dedca56485c38ed5a0","0x062214af1ea6dd6bf8895b92d394571c43970b6f967e1c794624d96071b25ad3","0x1e5be9428ddcf1f9b0cbafc28101e792ec5cf73852b0cd0b84fbff71b4490e09","0x2d4189bea5b1e30f63c64bd26df82f18bcaf885ec8887b54634b2557869ce87f","0x0f2e5d9a908850e9d44925e17d8b12d1adb1ed029799c9b5858598504242bbc0","0x3050dc85746a57931d99f3f35e77c2ba561fba0baa018b79ff1fd544026833ae","0x2a591a32437e5e0b875a137fd868bd1b6dbc003ff1b661f26e00627cc7c5cf47","0x27946841e1670ad9c65717016d0cedf524724217236e81b9fd0a264a36ebfb0e","0x0fc396e9d19d6e68e289602e292ee345542d0d28bf6de34fa62cc577cbdfb1df","0x08e7433a07a44c0c9c4dd4b273a2685bbd1a91fd5cf2b43409458fab42a23e1b","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x12bd9bfb029c3503a5c6deea87b0a0f11bb9f7ea584af2d48f3e48d7e09247ae","0x2ccc4810748c0a82dfc0f063d0b8c7999ffe9474653080e6ef92b3cb7a428784","0x08eb574d7fecadadb508c8bd35fdad06b99110609d679763c2e3645229b1b95a","0x0f1a65e747c8021ed7c454a4be1e89b1bce66ead9ed980fa98a7a050eafe98a1","0x1c8ff9e36684ec71614dee4c17859b06c742089f6029d3694a16e00dac9b57f1","0x0303101a8ba712aeca4da85b767ab8d3ecf489ec7d746f8ee20041717cc000e9","0x0aaf64c65e7088e5596108c9601467911fea809ca6540d79af77e6e66e36cd99","0x17caf164ce74ea7edfb1390e07763d2197797ec26661b92cde18a98d61d2fddc","0x18cb055c7ad6d01437725bb457681d81f3ecadc4f35d838a3c13daf25a44456a","0x2d78602b8bbcd32b36a99a6e2d248e7fe044ef1b50813133370412f9ef5299f0","0x2b139276ea86d426a115479e4154f72a6bd83a6253bf13e9670dc6b4664378f0","0x127c7837b384902c39a104036c09546728571c46c8166b1b9b13b3a615ebb781","0x05faa4816f83cf0189a482ad943c94b9ec6474002f2b327f8698763ad0ea0985","0x2f90359cc30ee693fb3aced96523cf7aebd152c22329eee56a398d9a4ac0628e","0x0a71beaf17a59c5a238f04c1f203848d87502c5057a78c13f0cfb0f9876e7714","0x2696c1e6d089556adaeb95c8a5e3065b00a393a38c2d69e9bd6ce8cdc49d87da","0x1f3d165a7dc6564a036e451eb9cb7f1e1cb1e6d29daa75e3f135ea3e58a79ccd","0x1473a660819bdd838d56122b72b32b267211e9f1103239480ec50fa85c9e1035","0x0a8ccaeb22451f391b3fc3467c8e6e900270a7afb7b510e8acf5a4f06f1c0888","0x03b3080afc0658cc87e307758cebc171921f43eca159b9dedf7f72aa8dd926bd","0x2dd7d6663fa0e1755dfafac352c361fcd64c7f4d53627e3646870ac169cc4a07","0x1ec54b883f5f35ccad0e75695af20790d9860104095bab34c9bf01628dd40cb9","0x193dff50f83c241f7a9e087a29ce72ecf3f6d8563593f786dcd04c32bcfd4ced","0x135122c0dae26cda8ca1c09de8225064ad86d10423ab0aaa53b481aa4626e1d6","0x08d5a56cbfab5aeed56d3cdd7fb6b30fc26b0c1a5b63fccd7fa44c53ba6fd35a","0x0d12f126dfa2daad3726d00ca339284cc22e36c6d81bb7a4b95c6f9598b60e7c","0x2e8b24bbdf2fd839d3c7cae1f0eeb96bfcfaeef30b27476f2fafcb17da78cd5e","0x2364acfe0cea39b7f749c5f303b99504977357925f810f684c60f35d16315211","0x06ca062eb70b8c51cfac35345e7b6b51f33a8ec9ebe204fb9b4911200bf508b7","0x266c0aa1ccb97186815bf69084f600d06ddd934e59a38dfe602ee5d6b9487f22","0x1d817537a49c6d0e3b4b65c6665334b91d7593142e60065048be9e55ceb5e7ab","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x05e9b7256a368df053c691952b59e9327a7c12ed322bbd6f72c669b9b9c26d49","0x25b77026673a1e613e50df0e88fb510973739d5f9064bd364079a9f884209632","0x25c9bc7a3f6aae3d43ff68b5614b34b5eaceff37157b37347995d231784ac1fd","0x085f69baef22680ae15f4801ef4361ebe9c7fc24a94b5bc2527dce8fb705439e","0x0d7c6b9ce31bfc32238a205455baf5ffe99cd30eb0f7bb5b504e1d4501e01382","0x1001a8cc4bc1221c814fba0eddcf3c40619b133373640c600de5bed0a0a05b10","0x20f5894be90e52977cb70f4f4cbd5101693db0360848939750db7e91109d54b6","0x22c09cb26db43f0599408b4daed0f4f496c66424e6affa41c14387d8e0af851b","0x24e5f41357798432426a9549d71e8cc681eaebacbe87f6e3bf38e85de5aa2f3d","0x06eb90100c736fbf2b87432d7821ecdc0b365024739bc36363d48b905973f5b9","0x000000000000000000000000000000ece6d09ed58e9f5661c01140b10558a8c2","0x000000000000000000000000000000000012b6e4f37adcb34b8e88ff8b6eebce","0x000000000000000000000000000000b226a2bb93593fa1fab19a44767828a3f5","0x00000000000000000000000000000000002b5b518342030543092e1428a7e33c","0x00000000000000000000000000000022ba33857034a0574c216eb3c1ddff3025","0x00000000000000000000000000000000001918e58df857985a7cf9eae7802165","0x00000000000000000000000000000045c2d840b96fb6106cc14dcad89dd5f675","0x00000000000000000000000000000000000afdfac1e3a1febdd0208867d44f98","0x00000000000000000000000000000042ebed6c5ec45d794f119aef24c192af0f","0x00000000000000000000000000000000002d05ef250900bbcc5751bbeb210d6a","0x00000000000000000000000000000060d604bdda48eecc90ed065bd9770e1323","0x00000000000000000000000000000000001fed91c63d0041660c1cbc84c2ffbb","0x00000000000000000000000000000054196b549cde36092e8184c7f4f7d878de","0x00000000000000000000000000000000000153f26a01294329922b492485cc31","0x00000000000000000000000000000056ebea579d10dbb440f0222931df2c0059","0x00000000000000000000000000000000000d2cbc61ce5b7cdd7fce398da4637b","0x000000000000000000000000000000e2b9512360b9797d96675d8a2fd2f7aa5d","0x000000000000000000000000000000000025742905f105ff895f74e7c3daa34a","0x000000000000000000000000000000a2dd7df55db59bd41b83518d4403fbc382","0x00000000000000000000000000000000002c1d9c3cbb9371d4cc4e9f900b9a46","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000bcf12ae40c9425c3e67654b84181f90502","0x00000000000000000000000000000000000b6d3faa8a71ff6ef1aa887b7307cf","0x0000000000000000000000000000001f6f719acc23b8f84808c0275d61cfb456","0x0000000000000000000000000000000000296030933ed0c134457ae71c393dfe","0x000000000000000000000000000000ebe1a57cdd7d3d763289b40ef5ed9a7ae0","0x000000000000000000000000000000000010f30483e7df51fca2316d3367603c","0x0000000000000000000000000000000149b7b283ab18060618c8e051864c03cd","0x00000000000000000000000000000000001ef7763235a3a25e241a5f06704dc3"] public_inputs = ["0x0000000000000000000000000000000000000000000000000000000000000003"] -verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84","0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae","0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16","0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1","0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c","0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7","0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8","0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c","0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5","0x00000000000000000000000000000000002002681bb417184b2df070a16a3858","0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511","0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223","0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7","0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c","0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130","0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f","0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3","0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592","0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3","0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1","0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0","0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c","0x0000000000000000000000000000009f825dde88092070747180d581c342444a","0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01","0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff","0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9","0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1","0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b","0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2","0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f","0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0","0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349","0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8","0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2","0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556","0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d","0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb","0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d","0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8","0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862","0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e","0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830","0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f","0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe","0x000000000000000000000000000000231147211b3c75e1f47d150e4bbd2fb22e","0x00000000000000000000000000000000000d19ee104a10d3c701cfd87473cbbe","0x0000000000000000000000000000006705f3f382637d00f698e2c5c94ed05ae9","0x00000000000000000000000000000000000b9c792da28bb60601dd7ce4b74e68","0x000000000000000000000000000000ac5acc8cc21e4ddb225c510670f80c80b3","0x00000000000000000000000000000000002da9d3fa57343e6998aba19429b9fa","0x0000000000000000000000000000004bacbf54b7c17a560df0af18b6d0d527be","0x00000000000000000000000000000000000faea33aeca2025b22c288964b21eb","0x000000000000000000000000000000492e756298d68d6e95de096055cc0336c3","0x00000000000000000000000000000000001a12a12f004859e5a3675c7315121b","0x000000000000000000000000000000893d521d512f30e6d32afbbc0cecd8ee00","0x00000000000000000000000000000000001674b3c1ef12c6da690631e0d86c04","0x000000000000000000000000000000aa6cb02a52e7a613873d4ac9b411349945","0x00000000000000000000000000000000001ecb1fe9c493add46751f9940f73e1","0x00000000000000000000000000000045b3d362ca82cba69fb2b9c733a5b8c351","0x000000000000000000000000000000000019a683586af466e331945b732d2f8c","0x000000000000000000000000000000fc79b052dfdfe67c0ecfc06b4267ffd694","0x00000000000000000000000000000000001336a70c396393038d5e9913744ac2","0x0000000000000000000000000000005450d29af1e9438e91cd33ddeb2548226e","0x000000000000000000000000000000000000993a602891cfd0e6f6ecf7404933","0x000000000000000000000000000000498efddab90a32e9b2db729ed6e9b40192","0x00000000000000000000000000000000002425efebe9628c63ca6fc28bdb5901","0x000000000000000000000000000000d8488157f875a21ab5f93f1c2b641f3de9","0x0000000000000000000000000000000000290f95ada3936604dc4b14df7504e3","0x0000000000000000000000000000005d6902187f3ed60dcce06fca211b40329a","0x00000000000000000000000000000000002b5870a6ba0b20aaa0178e5adfbc36","0x000000000000000000000000000000e5c2519171fa0e548fc3c4966ffc1ce570","0x00000000000000000000000000000000001cb8d8f4793b7debbdc429389dbf2d","0x000000000000000000000000000000a3ee22dd60456277b86c32a18982dcb185","0x00000000000000000000000000000000002493c99a3d068b03f8f2b8d28b57ce","0x000000000000000000000000000000f6c3731486320082c20ec71bbdc92196c1","0x00000000000000000000000000000000001ded39c4c8366469843cd63f09ecac","0x000000000000000000000000000000494997477ab161763e46601d95844837ef","0x00000000000000000000000000000000002e0cddbc5712d79b59cb3b41ebbcdd","0x000000000000000000000000000000426db4c64531d350750df62dbbc41a1bd9","0x0000000000000000000000000000000000303126892f664d8d505964d14315ec","0x00000000000000000000000000000076a6b2c6040c0c62bd59acfe3e3e125672","0x000000000000000000000000000000000000874a5ad262eecc6b565e0b085074","0x000000000000000000000000000000ef082fb517183c9c6841c2b8ef2ca1df04","0x0000000000000000000000000000000000127b2a745a1b74968c3edc18982b9b","0x000000000000000000000000000000c9efd4f8c3d56e1eb23d789a8f710d5be6","0x000000000000000000000000000000000015a18748490ff4c2b1871081954e86","0x000000000000000000000000000000a0011ef987dc016ab110eacd554a1d8bbf","0x00000000000000000000000000000000002097c84955059442a95df075833071","0x000000000000000000000000000000d38e9426ad3085b68b00a93c17897c2877","0x00000000000000000000000000000000002aecd48089890ea0798eb952c66824","0x00000000000000000000000000000078d8a9ce405ce559f441f2e71477ff3ddb","0x00000000000000000000000000000000001216bdb2f0d961bb8a7a23331d2150","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb","0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56","0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc","0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4"]" +verification_key = ["0x0000000000000000000000000000000000000000000000000000000000000020","0x0000000000000000000000000000000000000000000000000000000000000011","0x0000000000000000000000000000000000000000000000000000000000000001","0x00000000000000000000000000000060e430ad1c23bfcf3514323aae3f206e84","0x00000000000000000000000000000000001b5c3ff4c2458d8f481b1c068f27ae","0x000000000000000000000000000000bb510ab2112def34980e4fc6998ad9dd16","0x00000000000000000000000000000000000576e7c105b43e061e13cb877fefe1","0x000000000000000000000000000000ced074785d11857b065d8199e6669a601c","0x00000000000000000000000000000000000053b48a4098c1c0ae268f273952f7","0x000000000000000000000000000000d1d4b26e941db8168cee8f6de548ae0fd8","0x00000000000000000000000000000000001a9adf5a6dadc3d948bb61dfd63f4c","0x0000000000000000000000000000009ce1faac6f8de6ebb18f1db17372c82ad5","0x00000000000000000000000000000000002002681bb417184b2df070a16a3858","0x000000000000000000000000000000161baa651a8092e0e84725594de5aba511","0x00000000000000000000000000000000000be0064399c2a1efff9eb0cdcb2223","0x0000000000000000000000000000008673be6fd1bdbe980a29d8c1ded54381e7","0x000000000000000000000000000000000008a5158a7d9648cf1d234524c9fa0c","0x0000000000000000000000000000002b4fce6e4b1c72062b296d49bca2aa4130","0x00000000000000000000000000000000002e45a9eff4b6769e55fb710cded44f","0x00000000000000000000000000000072b85bf733758b76bcf97333efb85a23e3","0x000000000000000000000000000000000017da0ea508994fc82862715e4b5592","0x00000000000000000000000000000094fa74695cf058dba8ff35aec95456c6c3","0x0000000000000000000000000000000000211acddb851061c24b8f159e832bd1","0x000000000000000000000000000000303b5e5c531384b9a792e11702ad3bcab0","0x00000000000000000000000000000000000d336dff51a60b8833d5d7f6d4314c","0x0000000000000000000000000000009f825dde88092070747180d581c342444a","0x0000000000000000000000000000000000237fbd6511a03cca8cac01b555fe01","0x0000000000000000000000000000007c313205159495df6d8de292079a4844ff","0x000000000000000000000000000000000018facdfc468530dd45e8f7a1d38ce9","0x0000000000000000000000000000000d1ce33446fc3dc4ab40ca38d92dac74e1","0x00000000000000000000000000000000000852d8e3e0e8f4435af3e94222688b","0x0000000000000000000000000000006c04ee19ec1dfec87ed47d6d04aa158de2","0x000000000000000000000000000000000013240f97a584b45184c8ec31319b5f","0x000000000000000000000000000000cefb5d240b07ceb4be26ea429b6dc9d9e0","0x00000000000000000000000000000000002dad22022121d689f57fb38ca21349","0x000000000000000000000000000000c9f189f2a91aeb664ce376d8b157ba98f8","0x00000000000000000000000000000000002531a51ad54f124d58094b219818d2","0x000000000000000000000000000000ef1e6db71809307f677677e62b4163f556","0x0000000000000000000000000000000000272da4396fb2a7ee0638b9140e523d","0x0000000000000000000000000000002e54c0244a7732c87bc4712a76dd8c83fb","0x000000000000000000000000000000000007db77b3e04b7eba9643da57cbbe4d","0x000000000000000000000000000000e0dfe1ddd7f74ae0d636c910c3e85830d8","0x00000000000000000000000000000000000466fa9b57ec4664abd1505b490862","0x0000000000000000000000000000009ee55ae8a32fe5384c79907067cc27192e","0x00000000000000000000000000000000000799d0e465cec07ecb5238c854e830","0x0000000000000000000000000000001d5910ad361e76e1c241247a823733c39f","0x00000000000000000000000000000000002b03f2ccf7507564da2e6678bef8fe","0x000000000000000000000000000000231147211b3c75e1f47d150e4bbd2fb22e","0x00000000000000000000000000000000000d19ee104a10d3c701cfd87473cbbe","0x0000000000000000000000000000006705f3f382637d00f698e2c5c94ed05ae9","0x00000000000000000000000000000000000b9c792da28bb60601dd7ce4b74e68","0x000000000000000000000000000000ac5acc8cc21e4ddb225c510670f80c80b3","0x00000000000000000000000000000000002da9d3fa57343e6998aba19429b9fa","0x0000000000000000000000000000004bacbf54b7c17a560df0af18b6d0d527be","0x00000000000000000000000000000000000faea33aeca2025b22c288964b21eb","0x000000000000000000000000000000492e756298d68d6e95de096055cc0336c3","0x00000000000000000000000000000000001a12a12f004859e5a3675c7315121b","0x000000000000000000000000000000893d521d512f30e6d32afbbc0cecd8ee00","0x00000000000000000000000000000000001674b3c1ef12c6da690631e0d86c04","0x000000000000000000000000000000aa6cb02a52e7a613873d4ac9b411349945","0x00000000000000000000000000000000001ecb1fe9c493add46751f9940f73e1","0x00000000000000000000000000000045b3d362ca82cba69fb2b9c733a5b8c351","0x000000000000000000000000000000000019a683586af466e331945b732d2f8c","0x000000000000000000000000000000fc79b052dfdfe67c0ecfc06b4267ffd694","0x00000000000000000000000000000000001336a70c396393038d5e9913744ac2","0x0000000000000000000000000000005450d29af1e9438e91cd33ddeb2548226e","0x000000000000000000000000000000000000993a602891cfd0e6f6ecf7404933","0x000000000000000000000000000000498efddab90a32e9b2db729ed6e9b40192","0x00000000000000000000000000000000002425efebe9628c63ca6fc28bdb5901","0x000000000000000000000000000000d8488157f875a21ab5f93f1c2b641f3de9","0x0000000000000000000000000000000000290f95ada3936604dc4b14df7504e3","0x0000000000000000000000000000005d6902187f3ed60dcce06fca211b40329a","0x00000000000000000000000000000000002b5870a6ba0b20aaa0178e5adfbc36","0x000000000000000000000000000000e5c2519171fa0e548fc3c4966ffc1ce570","0x00000000000000000000000000000000001cb8d8f4793b7debbdc429389dbf2d","0x000000000000000000000000000000a3ee22dd60456277b86c32a18982dcb185","0x00000000000000000000000000000000002493c99a3d068b03f8f2b8d28b57ce","0x000000000000000000000000000000f6c3731486320082c20ec71bbdc92196c1","0x00000000000000000000000000000000001ded39c4c8366469843cd63f09ecac","0x000000000000000000000000000000494997477ab161763e46601d95844837ef","0x00000000000000000000000000000000002e0cddbc5712d79b59cb3b41ebbcdd","0x000000000000000000000000000000426db4c64531d350750df62dbbc41a1bd9","0x0000000000000000000000000000000000303126892f664d8d505964d14315ec","0x00000000000000000000000000000076a6b2c6040c0c62bd59acfe3e3e125672","0x000000000000000000000000000000000000874a5ad262eecc6b565e0b085074","0x000000000000000000000000000000ef082fb517183c9c6841c2b8ef2ca1df04","0x0000000000000000000000000000000000127b2a745a1b74968c3edc18982b9b","0x000000000000000000000000000000c9efd4f8c3d56e1eb23d789a8f710d5be6","0x000000000000000000000000000000000015a18748490ff4c2b1871081954e86","0x000000000000000000000000000000a0011ef987dc016ab110eacd554a1d8bbf","0x00000000000000000000000000000000002097c84955059442a95df075833071","0x000000000000000000000000000000d38e9426ad3085b68b00a93c17897c2877","0x00000000000000000000000000000000002aecd48089890ea0798eb952c66824","0x00000000000000000000000000000078d8a9ce405ce559f441f2e71477ff3ddb","0x00000000000000000000000000000000001216bdb2f0d961bb8a7a23331d2150","0x0000000000000000000000000000000000000000000000000000000000000001","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000002","0x0000000000000000000000000000000000000000000000000000000000000000","0x000000000000000000000000000000ee40d90bea71fba7a412dd61fcf34e8ceb","0x0000000000000000000000000000000000140b0936c323fd2471155617b6af56","0x0000000000000000000000000000002b90071823185c5ff8e440fd3d73b6fefc","0x00000000000000000000000000000000002b6c10790a5f6631c87d652e059df4"]