From 04e789f9053889dd0ff32439616713ac4002702e Mon Sep 17 00:00:00 2001 From: Jake Fecher Date: Mon, 27 Oct 2025 15:23:46 -0500 Subject: [PATCH 1/5] More trait docs --- .../noirc_frontend/src/elaborator/traits.rs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/compiler/noirc_frontend/src/elaborator/traits.rs b/compiler/noirc_frontend/src/elaborator/traits.rs index 602bce3daac..23a0e3afb17 100644 --- a/compiler/noirc_frontend/src/elaborator/traits.rs +++ b/compiler/noirc_frontend/src/elaborator/traits.rs @@ -191,6 +191,12 @@ use crate::{ use super::Elaborator; impl Elaborator<'_> { + /// For each trait: + /// 1. Desugar any trait constraints using implicit associated types into the explicit form, + /// mentioning all associated types. + /// 2. Resolves the trait's where clause. + /// 3. Resolves any bounds on associated types + /// 4. Resolves the trait's bounds (its listed super traits). pub fn collect_traits(&mut self, traits: &mut BTreeMap) { for (trait_id, unresolved_trait) in traits { self.local_module = unresolved_trait.module_id; @@ -199,6 +205,8 @@ impl Elaborator<'_> { this.current_trait = Some(*trait_id); let the_trait = this.interner.get_trait(*trait_id); + + // Add each type variable from the trait (including Self) into scope. let self_typevar = the_trait.self_type_typevar.clone(); let self_type = Type::TypeVariable(self_typevar.clone()); this.self_type = Some(self_type.clone()); @@ -209,8 +217,12 @@ impl Elaborator<'_> { &resolved_generics, ); + // Transform any constraints omitting their associated types (e.g. `I: Iterator`) + // into the explicit form (e.g. `I: Iterator { .add_trait_dependency(DependencyId::Trait(bound.trait_id), *trait_id); } + // TODO: Is it necessary to have both `where_clause` and `resolved_trait_bounds`? + // They both seem to be expressing trait constraints on this trait with the bounds + // limited to just constraints on `Self`. These may be able to be combined. this.interner.update_trait(*trait_id, |trait_def| { trait_def.set_trait_bounds(resolved_trait_bounds); trait_def.set_where_clause(where_clause); @@ -256,6 +271,10 @@ impl Elaborator<'_> { self.current_trait = None; } + /// Resolve the methods of each trait in an environment where the trait's generics are in scope. + /// + /// This mostly consists of resolving each parameter and any trait constraints. The trait + /// method bodies are not elaborated. pub fn collect_trait_methods(&mut self, traits: &mut BTreeMap) { for (trait_id, unresolved_trait) in traits { self.local_module = unresolved_trait.module_id; @@ -263,6 +282,7 @@ impl Elaborator<'_> { self.recover_generics(|this| { this.current_trait = Some(*trait_id); + // Put `Self` and other trait generics in scope let the_trait = this.interner.get_trait(*trait_id); let self_typevar = the_trait.self_type_typevar.clone(); let self_type = Type::TypeVariable(self_typevar.clone()); @@ -425,6 +445,8 @@ impl Elaborator<'_> { self.resolve_trait_bound_inner(bound, PathResolutionMode::MarkAsUsed) } + /// Resolve the given TraitBound, pushing error(s) if the path or any + /// types used failed to resolve. fn resolve_trait_bound_inner( &mut self, bound: &TraitBound, @@ -448,6 +470,11 @@ impl Elaborator<'_> { Some(ResolvedTraitBound { trait_id, trait_generics, location }) } + /// Adds the given trait constraints to scope as assumed trait impls. + /// + /// Since there is no global/local scope distinction for trait constraints, + /// care should be taken to manually remove these from scope (via + /// `remove_trait_constraints_from_scope`) after the desired item finishes resolving. pub(super) fn add_trait_constraints_to_scope<'a>( &mut self, constraints: impl Iterator, @@ -477,6 +504,10 @@ impl Elaborator<'_> { } } + /// The removing counterpart for `add_trait_constraints_to_scope`. + /// + /// This will only remove assumed trait impls from scope, but this + /// is always what is desired since true trait impls are permanent. pub(super) fn remove_trait_constraints_from_scope<'a>( &mut self, constraints: impl Iterator, @@ -571,6 +602,8 @@ impl Elaborator<'_> { } } + /// Resolves a traits methods, but does not elaborate their bodies. + /// Sets the FuncMeta for each trait method. fn resolve_trait_methods( &mut self, trait_id: TraitId, @@ -676,6 +709,9 @@ impl Elaborator<'_> { functions } + /// Defines the FuncMeta for this trait function. + /// + /// The bodies of each function (if they exist) are not elaborated. #[allow(clippy::too_many_arguments)] pub fn resolve_trait_function( &mut self, @@ -836,6 +872,10 @@ pub(crate) fn check_trait_impl_method_matches_declaration( errors } +/// Check the given function type matches the expected one. +/// +/// This is used to check if a trait impl's function type matches the declared function in the +/// original trait declaration - while handling the appropriate generic substitutions. #[allow(clippy::too_many_arguments)] fn check_function_type_matches_expected_type( expected: &Type, From ca59c05f40b0c9564ec4e3c2160aee4881b96292 Mon Sep 17 00:00:00 2001 From: jfecher Date: Tue, 28 Oct 2025 10:21:47 -0500 Subject: [PATCH 2/5] Update compiler/noirc_frontend/src/elaborator/traits.rs Co-authored-by: Maxim Vezenov --- compiler/noirc_frontend/src/elaborator/traits.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/noirc_frontend/src/elaborator/traits.rs b/compiler/noirc_frontend/src/elaborator/traits.rs index 23a0e3afb17..7107ee3cd9d 100644 --- a/compiler/noirc_frontend/src/elaborator/traits.rs +++ b/compiler/noirc_frontend/src/elaborator/traits.rs @@ -218,7 +218,7 @@ impl Elaborator<'_> { ); // Transform any constraints omitting their associated types (e.g. `I: Iterator`) - // into the explicit form (e.g. `I: Iterator`), returning // any fresh generics created in the process (`[FreshGeneric]` here). let new_generics = this.desugar_trait_constraints(&mut unresolved_trait.trait_def.where_clause); From b3fa159434af53c224ee94679a1efdd934f528a3 Mon Sep 17 00:00:00 2001 From: jfecher Date: Tue, 28 Oct 2025 10:23:29 -0500 Subject: [PATCH 3/5] Update compiler/noirc_frontend/src/elaborator/traits.rs Co-authored-by: Maxim Vezenov --- compiler/noirc_frontend/src/elaborator/traits.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/noirc_frontend/src/elaborator/traits.rs b/compiler/noirc_frontend/src/elaborator/traits.rs index 7107ee3cd9d..03034c5b32e 100644 --- a/compiler/noirc_frontend/src/elaborator/traits.rs +++ b/compiler/noirc_frontend/src/elaborator/traits.rs @@ -474,7 +474,7 @@ impl Elaborator<'_> { /// /// Since there is no global/local scope distinction for trait constraints, /// care should be taken to manually remove these from scope (via - /// `remove_trait_constraints_from_scope`) after the desired item finishes resolving. + /// [Self::remove_trait_constraints_from_scope]) after the desired item finishes resolving. pub(super) fn add_trait_constraints_to_scope<'a>( &mut self, constraints: impl Iterator, From d131419fd2459e7ea1be7572b13db2714856e992 Mon Sep 17 00:00:00 2001 From: jfecher Date: Tue, 28 Oct 2025 10:23:41 -0500 Subject: [PATCH 4/5] Update compiler/noirc_frontend/src/elaborator/traits.rs Co-authored-by: Maxim Vezenov --- compiler/noirc_frontend/src/elaborator/traits.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/noirc_frontend/src/elaborator/traits.rs b/compiler/noirc_frontend/src/elaborator/traits.rs index 03034c5b32e..6ce9ccaed51 100644 --- a/compiler/noirc_frontend/src/elaborator/traits.rs +++ b/compiler/noirc_frontend/src/elaborator/traits.rs @@ -504,7 +504,7 @@ impl Elaborator<'_> { } } - /// The removing counterpart for `add_trait_constraints_to_scope`. + /// The removing counterpart for [Self::add_trait_constraints_to_scope]. /// /// This will only remove assumed trait impls from scope, but this /// is always what is desired since true trait impls are permanent. From 5102d610a0df2a9d8b101634d8b437f53c038dd3 Mon Sep 17 00:00:00 2001 From: jfecher Date: Tue, 28 Oct 2025 10:43:36 -0500 Subject: [PATCH 5/5] Update compiler/noirc_frontend/src/elaborator/traits.rs Co-authored-by: Maxim Vezenov --- compiler/noirc_frontend/src/elaborator/traits.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/noirc_frontend/src/elaborator/traits.rs b/compiler/noirc_frontend/src/elaborator/traits.rs index 6ce9ccaed51..6220d1f93c9 100644 --- a/compiler/noirc_frontend/src/elaborator/traits.rs +++ b/compiler/noirc_frontend/src/elaborator/traits.rs @@ -602,7 +602,7 @@ impl Elaborator<'_> { } } - /// Resolves a traits methods, but does not elaborate their bodies. + /// Resolves a trait's methods, but does not elaborate their bodies. /// Sets the FuncMeta for each trait method. fn resolve_trait_methods( &mut self,