diff --git a/compiler/noirc_frontend/src/elaborator/path_resolution.rs b/compiler/noirc_frontend/src/elaborator/path_resolution.rs index a68991becb7..51673342fef 100644 --- a/compiler/noirc_frontend/src/elaborator/path_resolution.rs +++ b/compiler/noirc_frontend/src/elaborator/path_resolution.rs @@ -9,7 +9,7 @@ use crate::hir::resolution::visibility::item_in_module_is_visible; use crate::locations::ReferencesTracker; use crate::node_interner::{FuncId, GlobalId, StructId, TraitId, TypeAliasId}; -use crate::Type; +use crate::{Shared, Type, TypeAlias}; use super::types::SELF_TYPE_NAME; use super::Elaborator; @@ -218,18 +218,8 @@ impl<'context> Elaborator<'context> { ), ModuleDefId::TypeAliasId(id) => { let type_alias = self.interner.get_type_alias(id); - let type_alias = type_alias.borrow(); - - let module_id = match &type_alias.typ { - Type::Struct(struct_id, _generics) => struct_id.borrow().id.module_id(), - Type::Error => { - return Err(PathResolutionError::Unresolved(last_ident.clone())); - } - _ => { - // For now we only allow type aliases that point to structs. - // The more general case is captured here: https://github.com/noir-lang/noir/issues/6398 - panic!("Type alias in path not pointing to struct not yet supported") - } + let Some(module_id) = get_type_alias_module_def_id(&type_alias) else { + return Err(PathResolutionError::Unresolved(last_ident.clone())); }; ( @@ -345,3 +335,18 @@ fn merge_intermediate_path_resolution_item_with_module_def_id( }, } } + +fn get_type_alias_module_def_id(type_alias: &Shared) -> Option { + let type_alias = type_alias.borrow(); + + match &type_alias.typ { + Type::Struct(struct_id, _generics) => Some(struct_id.borrow().id.module_id()), + Type::Alias(type_alias, _generics) => get_type_alias_module_def_id(type_alias), + Type::Error => None, + _ => { + // For now we only allow type aliases that point to structs. + // The more general case is captured here: https://github.com/noir-lang/noir/issues/6398 + panic!("Type alias in path not pointing to struct not yet supported") + } + } +} diff --git a/compiler/noirc_frontend/src/elaborator/patterns.rs b/compiler/noirc_frontend/src/elaborator/patterns.rs index 0406321de42..133473219f6 100644 --- a/compiler/noirc_frontend/src/elaborator/patterns.rs +++ b/compiler/noirc_frontend/src/elaborator/patterns.rs @@ -604,17 +604,11 @@ impl<'context> Elaborator<'context> { alias_generics }; - // Now instantiate the underlying struct with those generics, the struct might + // Now instantiate the underlying struct or alias with those generics, the struct might // have more generics than those in the alias, like in this example: // // type Alias = Struct; - let typ = type_alias.get_type(&generics); - let Type::Struct(_, generics) = typ else { - // See https://github.com/noir-lang/noir/issues/6398 - panic!("Expected type alias to point to struct") - }; - - generics + get_type_alias_generics(&type_alias, &generics) } PathResolutionItem::TraitFunction(trait_id, Some(generics), _func_id) => { let trait_ = self.interner.get_trait(trait_id); @@ -880,3 +874,14 @@ impl<'context> Elaborator<'context> { (id, typ) } } + +fn get_type_alias_generics(type_alias: &TypeAlias, generics: &[Type]) -> Vec { + let typ = type_alias.get_type(generics); + match typ { + Type::Struct(_, generics) => generics, + Type::Alias(type_alias, generics) => { + get_type_alias_generics(&type_alias.borrow(), &generics) + } + _ => panic!("Expected type alias to point to struct or alias"), + } +} diff --git a/compiler/noirc_frontend/src/tests/aliases.rs b/compiler/noirc_frontend/src/tests/aliases.rs index 8d3433299f6..1a5621c8adb 100644 --- a/compiler/noirc_frontend/src/tests/aliases.rs +++ b/compiler/noirc_frontend/src/tests/aliases.rs @@ -47,3 +47,31 @@ fn alias_in_let_pattern() { "#; assert_no_errors(src); } + +#[test] +fn double_alias_in_path() { + let src = r#" + struct Foo {} + + impl Foo { + fn new() -> Self { + Self {} + } + } + + type FooAlias1 = Foo; + type FooAlias2 = FooAlias1; + + fn main() { + let _ = FooAlias2::new(); + } + "#; + assert_no_errors(src); +} + +#[test] +fn double_generic_alias_in_path() { + let src = r#" + "#; + assert_no_errors(src); +} diff --git a/test_programs/compile_success_empty/double_generic_alias_in_path/Nargo.toml b/test_programs/compile_success_empty/double_generic_alias_in_path/Nargo.toml new file mode 100644 index 00000000000..aaebee8d6ef --- /dev/null +++ b/test_programs/compile_success_empty/double_generic_alias_in_path/Nargo.toml @@ -0,0 +1,7 @@ +[package] +name = "double_generic_alias_in_path" +type = "bin" +authors = [""] +compiler_version = ">=0.32.0" + +[dependencies] diff --git a/test_programs/compile_success_empty/double_generic_alias_in_path/src/main.nr b/test_programs/compile_success_empty/double_generic_alias_in_path/src/main.nr new file mode 100644 index 00000000000..09f2e5c4b43 --- /dev/null +++ b/test_programs/compile_success_empty/double_generic_alias_in_path/src/main.nr @@ -0,0 +1,14 @@ +struct Foo {} + +impl Foo { + fn new() -> Self { + Self {} + } +} + +type FooAlias1 = Foo; +type FooAlias2 = FooAlias1; + +fn main() { + let _ = FooAlias2::new(); +}