diff --git a/compiler/noirc_frontend/src/hir/resolution/traits.rs b/compiler/noirc_frontend/src/hir/resolution/traits.rs index ccae8c6dd03..3d355fd4447 100644 --- a/compiler/noirc_frontend/src/hir/resolution/traits.rs +++ b/compiler/noirc_frontend/src/hir/resolution/traits.rs @@ -124,6 +124,7 @@ fn resolve_trait_methods( let mut resolver = Resolver::new(interner, &path_resolver, def_maps, file); resolver.add_generics(generics); + resolver.add_existing_generics(&unresolved_trait.trait_def.generics, trait_generics); resolver.add_existing_generic("Self", name_span, self_typevar); resolver.set_self_type(Some(self_type.clone())); @@ -207,16 +208,16 @@ fn collect_trait_impl_methods( if overrides.is_empty() { if let Some(default_impl) = &method.default_impl { + // copy 'where' clause from unresolved trait impl + let mut default_impl_clone = default_impl.clone(); + default_impl_clone.def.where_clause.extend(trait_impl.where_clause.clone()); + let func_id = interner.push_empty_fn(); let module = ModuleId { local_id: trait_impl.module_id, krate: crate_id }; let location = Location::new(default_impl.def.span, trait_impl.file_id); interner.push_function(func_id, &default_impl.def, module, location); func_ids_in_trait.insert(func_id); - ordered_methods.push(( - method.default_impl_module_id, - func_id, - *default_impl.clone(), - )); + ordered_methods.push((method.default_impl_module_id, func_id, *default_impl_clone)); } else { let error = DefCollectorErrorKind::TraitMissingMethod { trait_name: interner.get_trait(trait_id).name.clone(), diff --git a/compiler/noirc_frontend/src/tests.rs b/compiler/noirc_frontend/src/tests.rs index cf2d7dbe153..b2cc7eee9f8 100644 --- a/compiler/noirc_frontend/src/tests.rs +++ b/compiler/noirc_frontend/src/tests.rs @@ -746,6 +746,27 @@ mod test { } } + #[test] + fn test_impl_self_within_default_def() { + let src = " + trait Bar { + fn ok(self) -> Self; + + fn ref_ok(self) -> Self { + self.ok() + } + } + + impl Bar for (T, T) where T: Bar { + fn ok(self) -> Self { + self + } + }"; + let errors = get_program_errors(src); + errors.iter().for_each(|err| println!("{:?}", err)); + assert!(errors.is_empty()); + } + #[test] fn check_trait_as_type_as_fn_parameter() { let src = " diff --git a/test_programs/compile_success_empty/impl_from_where_impl/Nargo.toml b/test_programs/compile_success_empty/impl_from_where_impl/Nargo.toml new file mode 100644 index 00000000000..5894e457dd8 --- /dev/null +++ b/test_programs/compile_success_empty/impl_from_where_impl/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "impl_from_where_impl" +type = "bin" +authors = [""] +compiler_version = ">=0.27.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/impl_from_where_impl/src/main.nr b/test_programs/compile_success_empty/impl_from_where_impl/src/main.nr new file mode 100644 index 00000000000..3cec46bdfcd --- /dev/null +++ b/test_programs/compile_success_empty/impl_from_where_impl/src/main.nr @@ -0,0 +1,15 @@ +trait Bar { + fn ok(self) -> Self; + + fn ref_ok(self) -> Self { + self.ok() + } +} + +impl Bar for (T, T) where T: Bar { + fn ok(self) -> Self { + self + } +} + +fn main() {}