From 7950bc943c8558649432c85e213df8f8d1835287 Mon Sep 17 00:00:00 2001 From: jfecher Date: Thu, 26 Oct 2023 05:24:22 -0500 Subject: [PATCH] feat: Make generic impls callable (#3297) --- .../src/hir/def_collector/dc_crate.rs | 17 +++++++++-------- .../src/hir/def_collector/dc_mod.rs | 1 + .../trait_generics/src/main.nr | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs index 50618c1ca8b..86b22992555 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_crate.rs @@ -92,6 +92,7 @@ pub struct UnresolvedTraitImpl { pub trait_path: Path, pub object_type: UnresolvedType, pub methods: UnresolvedFunctions, + pub generics: UnresolvedGenerics, } #[derive(Clone)] @@ -529,6 +530,7 @@ fn collect_trait_impl( let path_resolver = StandardPathResolver::new(module); let file = def_maps[&crate_id].file_id(trait_impl.module_id); let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file); + resolver.add_generics(&trait_impl.generics); let typ = resolver.resolve_type(unresolved_type); errors.extend(take_errors(trait_impl.file_id, resolver)); @@ -964,13 +966,11 @@ fn resolve_trait_impls( let self_type_span = unresolved_type.span; - let self_type = { - let mut resolver = - Resolver::new(interner, &path_resolver, &context.def_maps, trait_impl.file_id); - resolver.resolve_type(unresolved_type.clone()) - }; - - let maybe_trait_id = trait_impl.trait_id; + let mut resolver = + Resolver::new(interner, &path_resolver, &context.def_maps, trait_impl.file_id); + resolver.add_generics(&trait_impl.generics); + let self_type = resolver.resolve_type(unresolved_type.clone()); + let generics = resolver.get_generics().to_vec(); let mut impl_methods = resolve_function_set( interner, @@ -978,10 +978,11 @@ fn resolve_trait_impls( &context.def_maps, trait_impl.methods.clone(), Some(self_type.clone()), - vec![], // TODO + generics, errors, ); + let maybe_trait_id = trait_impl.trait_id; if let Some(trait_id) = maybe_trait_id { for (_, func) in &impl_methods { interner.set_function_trait(*func, self_type.clone(), trait_id); diff --git a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs index 4af910b6f84..17c85abbd8b 100644 --- a/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs +++ b/compiler/noirc_frontend/src/hir/def_collector/dc_mod.rs @@ -160,6 +160,7 @@ impl<'a> ModCollector<'a> { trait_path: trait_name, methods: unresolved_functions, object_type: trait_impl.object_type, + generics: trait_impl.impl_generics, trait_id: None, // will be filled later }; diff --git a/tooling/nargo_cli/tests/compile_success_empty/trait_generics/src/main.nr b/tooling/nargo_cli/tests/compile_success_empty/trait_generics/src/main.nr index c44366c006e..ccda969f930 100644 --- a/tooling/nargo_cli/tests/compile_success_empty/trait_generics/src/main.nr +++ b/tooling/nargo_cli/tests/compile_success_empty/trait_generics/src/main.nr @@ -24,4 +24,22 @@ fn main() { // Types matching multiple impls will currently choose // the first matching one instead of erroring assert(z.foo() == 32); + + // Ensure we can call a generic impl + let x: u8 = 7; + let y: i8 = 8; + let s2_u8 = S2 { x }; + let s2_i8 = S2 { x: y }; + assert(s2_u8.t2().x == 7); + assert(s2_i8.t2().x == 8); +} + +trait T2 { + fn t2(self) -> Self; +} + +struct S2 { x: T } + +impl T2 for S2 { + fn t2(self) -> Self { self } }