diff --git a/src/canonicalize/Can.zig b/src/canonicalize/Can.zig index 09b6e998c6..21fe8ab482 100644 --- a/src/canonicalize/Can.zig +++ b/src/canonicalize/Can.zig @@ -922,10 +922,21 @@ fn processAssociatedItemsSecondPass( const def_idx_u16: u16 = @intCast(@intFromEnum(def_idx)); try self.env.setExposedNodeIndexById(decl_ident, def_idx_u16); - // Also register by the type-qualified name for type modules - // This is needed so lookups like "Builtin.Str.is_empty" work + // Compute type-qualified name first (e.g., "Bool.not") before exposing + const type_qualified_idx = try self.env.insertQualifiedIdent(self.env.getIdent(parent_type_name), decl_text); + + // Always register by the type-qualified name (e.g., "Bool.not") + // This is needed so lookups like "Bool.not" work from other modules + if (type_qualified_idx.idx != decl_ident.idx) { + try self.env.setExposedNodeIndexById(type_qualified_idx, def_idx_u16); + } + + // Also register by the fully qualified name for type modules (e.g., "Builtin.Bool.not") + // This is needed so lookups like "Builtin.Bool.not" work if (self.env.module_kind == .type_module) { - try self.env.setExposedNodeIndexById(qualified_idx, def_idx_u16); + if (qualified_idx.idx != type_qualified_idx.idx and qualified_idx.idx != decl_ident.idx) { + try self.env.setExposedNodeIndexById(qualified_idx, def_idx_u16); + } } // Make the real pattern available in current scope (replaces placeholder) @@ -939,7 +950,6 @@ fn processAssociatedItemsSecondPass( try self.updatePlaceholder(current_scope, decl_ident, pattern_idx); // Update type-qualified name (e.g., "MyBool.my_not") - const type_qualified_idx = try self.env.insertQualifiedIdent(self.env.getIdent(parent_type_name), decl_text); if (type_qualified_idx.idx != decl_ident.idx) { try self.updatePlaceholder(current_scope, type_qualified_idx, pattern_idx); } @@ -974,10 +984,21 @@ fn processAssociatedItemsSecondPass( const def_idx_u16: u16 = @intCast(@intFromEnum(def_idx)); try self.env.setExposedNodeIndexById(name_ident, def_idx_u16); - // Also register by the type-qualified name for type modules + // Compute type-qualified name first (e.g., "Str.is_empty") before exposing + const type_qualified_idx = try self.env.insertQualifiedIdent(self.env.getIdent(parent_type_name), name_text); + + // Always register by the type-qualified name (e.g., "Str.is_empty") + // This is needed so lookups like "Str.is_empty" work from other modules + if (type_qualified_idx.idx != name_ident.idx) { + try self.env.setExposedNodeIndexById(type_qualified_idx, def_idx_u16); + } + + // Also register by the fully qualified name for type modules (e.g., "Builtin.Str.is_empty") // This is needed so lookups like "Builtin.Str.is_empty" work if (self.env.module_kind == .type_module) { - try self.env.setExposedNodeIndexById(qualified_idx, def_idx_u16); + if (qualified_idx.idx != type_qualified_idx.idx and qualified_idx.idx != name_ident.idx) { + try self.env.setExposedNodeIndexById(qualified_idx, def_idx_u16); + } } // Make the real pattern available in current scope (replaces placeholder) @@ -989,7 +1010,6 @@ fn processAssociatedItemsSecondPass( try self.updatePlaceholder(current_scope, name_ident, pattern_idx); // Update type-qualified name (e.g., "List.is_empty") - const type_qualified_idx = try self.env.insertQualifiedIdent(self.env.getIdent(parent_type_name), name_text); if (type_qualified_idx.idx != name_ident.idx) { try self.updatePlaceholder(current_scope, type_qualified_idx, pattern_idx); } @@ -1022,6 +1042,19 @@ fn processAssociatedItemsSecondPass( // (e.g., "bar" not "Foo.bar") const def_idx_u16: u16 = @intCast(@intFromEnum(def_idx)); try self.env.setExposedNodeIndexById(decl_ident, def_idx_u16); + + // Compute type-qualified name (e.g., "MyType.bar") and expose it + const type_qualified_idx = try self.env.insertQualifiedIdent(self.env.getIdent(parent_type_name), decl_text); + if (type_qualified_idx.idx != decl_ident.idx) { + try self.env.setExposedNodeIndexById(type_qualified_idx, def_idx_u16); + } + + // Also register by the fully qualified name for type modules (e.g., "Module.MyType.bar") + if (self.env.module_kind == .type_module) { + if (qualified_idx.idx != type_qualified_idx.idx and qualified_idx.idx != decl_ident.idx) { + try self.env.setExposedNodeIndexById(qualified_idx, def_idx_u16); + } + } } } else { // Non-identifier patterns are not supported in associated blocks