Skip to content

Commit 32210df

Browse files
committed
More fixes
1 parent b1d0e72 commit 32210df

File tree

10 files changed

+321
-364
lines changed

10 files changed

+321
-364
lines changed

src/canonicalize/Can.zig

Lines changed: 131 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,21 @@ const TypeVarProblemKind = enum {
5151
type_var_ending_in_underscore,
5252
};
5353

54+
const ModuleFoundStatus = enum {
55+
module_was_found,
56+
module_not_found,
57+
};
58+
59+
const TypeBindingLocation = struct {
60+
scope_index: usize,
61+
binding: *Scope.TypeBinding,
62+
};
63+
64+
const TypeBindingLocationConst = struct {
65+
scope_index: usize,
66+
binding: *const Scope.TypeBinding,
67+
};
68+
5469
const TypeVarProblem = struct {
5570
ident: Ident.Idx,
5671
problem: TypeVarProblemKind,
@@ -1376,7 +1391,7 @@ fn createExposedScope(
13761391

13771392
// Use a dummy statement index - we just need to track that it's exposed
13781393
const dummy_idx = @as(Statement.Idx, @enumFromInt(0));
1379-
try self.exposed_scope.put(gpa, .type_decl, ident_idx, dummy_idx);
1394+
try self.exposed_scope.type_bindings.put(gpa, ident_idx, Scope.TypeBinding{ .local_nominal = dummy_idx });
13801395
}
13811396

13821397
// Store by text in a temporary hash map, since indices may change
@@ -1409,7 +1424,7 @@ fn createExposedScope(
14091424

14101425
// Use a dummy statement index - we just need to track that it's exposed
14111426
const dummy_idx = @as(Statement.Idx, @enumFromInt(0));
1412-
try self.exposed_scope.put(gpa, .type_decl, ident_idx, dummy_idx);
1427+
try self.exposed_scope.type_bindings.put(gpa, ident_idx, Scope.TypeBinding{ .local_nominal = dummy_idx });
14131428
}
14141429

14151430
// Store by text in a temporary hash map, since indices may change
@@ -5634,12 +5649,56 @@ fn canonicalizeTypeAnnoBasicType(
56345649
.base = .{ .builtin = builtin_type },
56355650
} }, region);
56365651
} else {
5637-
// If it's not a builtin, look up in scope
5638-
if (self.scopeLookupTypeDecl(type_name_ident)) |type_decl_idx| {
5639-
return try self.env.addTypeAnno(CIR.TypeAnno{ .lookup = .{
5640-
.name = type_name_ident,
5641-
.base = .{ .local = .{ .decl_idx = type_decl_idx } },
5642-
} }, region);
5652+
// If it's not a builtin, look up in scope using unified type bindings
5653+
if (self.scopeLookupTypeBinding(type_name_ident)) |binding_location| {
5654+
const binding = binding_location.binding.*;
5655+
return switch (binding) {
5656+
.local_nominal => |stmt| try self.env.addTypeAnno(CIR.TypeAnno{ .lookup = .{
5657+
.name = type_name_ident,
5658+
.base = .{ .local = .{ .decl_idx = stmt } },
5659+
} }, region),
5660+
.local_alias => |stmt| try self.env.addTypeAnno(CIR.TypeAnno{ .lookup = .{
5661+
.name = type_name_ident,
5662+
.base = .{ .local = .{ .decl_idx = stmt } },
5663+
} }, region),
5664+
.associated_nominal => |stmt| try self.env.addTypeAnno(CIR.TypeAnno{ .lookup = .{
5665+
.name = type_name_ident,
5666+
.base = .{ .local = .{ .decl_idx = stmt } },
5667+
} }, region),
5668+
.external_nominal => |external| blk: {
5669+
const import_idx = external.import_idx orelse {
5670+
break :blk try self.env.pushMalformed(TypeAnno.Idx, Diagnostic{ .module_not_imported = .{
5671+
.module_name = external.module_ident,
5672+
.region = type_name_region,
5673+
} });
5674+
};
5675+
5676+
const target_node_idx = external.target_node_idx orelse {
5677+
// Check if the module was not found
5678+
if (external.module_not_found) {
5679+
break :blk try self.env.pushMalformed(TypeAnno.Idx, Diagnostic{ .type_from_missing_module = .{
5680+
.module_name = external.module_ident,
5681+
.type_name = type_name_ident,
5682+
.region = type_name_region,
5683+
} });
5684+
} else {
5685+
break :blk try self.env.pushMalformed(TypeAnno.Idx, Diagnostic{ .type_not_exposed = .{
5686+
.module_name = external.module_ident,
5687+
.type_name = type_name_ident,
5688+
.region = type_name_region,
5689+
} });
5690+
}
5691+
};
5692+
5693+
break :blk try self.env.addTypeAnno(CIR.TypeAnno{ .lookup = .{
5694+
.name = type_name_ident,
5695+
.base = .{ .external = .{
5696+
.module_idx = import_idx,
5697+
.target_node_idx = target_node_idx,
5698+
} },
5699+
} }, region);
5700+
},
5701+
};
56435702
}
56445703

56455704
// Check if this is an auto-imported type from module_envs
@@ -7316,12 +7375,14 @@ fn scopeIntroduceTypeDecl(
73167375
while (i > 0) {
73177376
i -= 1;
73187377
const scope = &self.scopes.items[i];
7319-
switch (scope.lookupTypeDecl(name_ident)) {
7320-
.found => |type_decl_idx| {
7321-
shadowed_in_parent = type_decl_idx;
7322-
break;
7323-
},
7324-
.not_found => continue,
7378+
if (scope.type_bindings.get(name_ident)) |binding| {
7379+
shadowed_in_parent = switch (binding) {
7380+
.local_nominal => |stmt| stmt,
7381+
.local_alias => |stmt| stmt,
7382+
.associated_nominal => |stmt| stmt,
7383+
.external_nominal => null,
7384+
};
7385+
if (shadowed_in_parent) |_| break;
73257386
}
73267387
}
73277388
}
@@ -7427,15 +7488,40 @@ fn scopeLookupTypeDecl(self: *Self, ident_idx: Ident.Idx) ?Statement.Idx {
74277488
i -= 1;
74287489
const scope = &self.scopes.items[i];
74297490

7430-
// Check for type aliases (unqualified names in associated blocks)
7431-
if (scope.lookupTypeAlias(ident_idx)) |aliased_decl| {
7432-
return aliased_decl;
7491+
// Check unified type bindings
7492+
if (scope.type_bindings.get(ident_idx)) |binding| {
7493+
return switch (binding) {
7494+
.local_nominal => |stmt| stmt,
7495+
.local_alias => |stmt| stmt,
7496+
.associated_nominal => |stmt| stmt,
7497+
.external_nominal => null, // External types don't have local Statement.Idx
7498+
};
74337499
}
7500+
}
74347501

7435-
// Check regular type declarations
7436-
switch (scope.lookupTypeDecl(ident_idx)) {
7437-
.found => |type_decl_idx| return type_decl_idx,
7438-
.not_found => continue,
7502+
return null;
7503+
}
7504+
7505+
fn scopeLookupTypeBinding(self: *Self, ident_idx: Ident.Idx) ?TypeBindingLocation {
7506+
var i = self.scopes.items.len;
7507+
while (i > 0) {
7508+
i -= 1;
7509+
const scope = &self.scopes.items[i];
7510+
if (scope.type_bindings.getPtr(ident_idx)) |binding_ptr| {
7511+
return TypeBindingLocation{ .scope_index = i, .binding = binding_ptr };
7512+
}
7513+
}
7514+
7515+
return null;
7516+
}
7517+
7518+
fn scopeLookupTypeBindingConst(self: *const Self, ident_idx: Ident.Idx) ?TypeBindingLocationConst {
7519+
var i = self.scopes.items.len;
7520+
while (i > 0) {
7521+
i -= 1;
7522+
const scope = &self.scopes.items[i];
7523+
if (scope.type_bindings.getPtr(ident_idx)) |binding_ptr| {
7524+
return TypeBindingLocationConst{ .scope_index = i, .binding = binding_ptr };
74397525
}
74407526
}
74417527

@@ -7581,6 +7667,30 @@ pub fn scopeIntroduceExposedItem(self: *Self, item_name: Ident.Idx, item_info: S
75817667
}
75827668
}
75837669

7670+
/// Set an external type binding for an imported nominal type
7671+
fn setExternalTypeBinding(
7672+
self: *Self,
7673+
scope: *Scope,
7674+
local_ident: Ident.Idx,
7675+
module_ident: Ident.Idx,
7676+
original_ident: Ident.Idx,
7677+
target_node_idx: ?u16,
7678+
module_import_idx: CIR.Import.Idx,
7679+
origin_region: Region,
7680+
module_found_status: ModuleFoundStatus,
7681+
) !void {
7682+
try scope.type_bindings.put(self.env.gpa, local_ident, Scope.TypeBinding{
7683+
.external_nominal = .{
7684+
.module_ident = module_ident,
7685+
.original_ident = original_ident,
7686+
.target_node_idx = target_node_idx,
7687+
.import_idx = module_import_idx,
7688+
.origin_region = origin_region,
7689+
.module_not_found = module_found_status == .module_not_found,
7690+
},
7691+
});
7692+
}
7693+
75847694
/// Look up an exposed item in parent scopes (for shadowing detection)
75857695
fn scopeLookupExposedItemInParentScopes(self: *const Self, item_name: Ident.Idx) ?Scope.ExposedItemInfo {
75867696
// Search from second-innermost to outermost scope (excluding current scope)

src/canonicalize/Diagnostic.zig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ pub const Diagnostic = union(enum) {
118118
type_name: Ident.Idx,
119119
region: Region,
120120
},
121+
type_from_missing_module: struct {
122+
module_name: Ident.Idx,
123+
type_name: Ident.Idx,
124+
region: Region,
125+
},
121126
module_not_imported: struct {
122127
module_name: Ident.Idx,
123128
region: Region,
@@ -269,6 +274,7 @@ pub const Diagnostic = union(enum) {
269274
.module_not_found => |d| d.region,
270275
.value_not_exposed => |d| d.region,
271276
.type_not_exposed => |d| d.region,
277+
.type_from_missing_module => |d| d.region,
272278
.module_not_imported => |d| d.region,
273279
.too_many_exports => |d| d.region,
274280
.undeclared_type => |d| d.region,

src/canonicalize/Node.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ pub const Tag = enum {
188188
diag_module_not_found,
189189
diag_value_not_exposed,
190190
diag_type_not_exposed,
191+
diag_type_from_missing_module,
191192
diag_module_not_imported,
192193
diag_too_many_exports,
193194
diag_nominal_type_redeclared,

src/canonicalize/NodeStore.zig

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ pub fn deinit(store: *NodeStore) void {
128128
/// when adding/removing variants from ModuleEnv unions. Update these when modifying the unions.
129129
///
130130
/// Count of the diagnostic nodes in the ModuleEnv
131-
pub const MODULEENV_DIAGNOSTIC_NODE_COUNT = 56;
131+
pub const MODULEENV_DIAGNOSTIC_NODE_COUNT = 57;
132132
/// Count of the expression nodes in the ModuleEnv
133133
pub const MODULEENV_EXPR_NODE_COUNT = 33;
134134
/// Count of the statement nodes in the ModuleEnv
@@ -2831,6 +2831,12 @@ pub fn addDiagnostic(store: *NodeStore, reason: CIR.Diagnostic) Allocator.Error!
28312831
node.data_1 = @as(u32, @bitCast(r.module_name));
28322832
node.data_2 = @as(u32, @bitCast(r.type_name));
28332833
},
2834+
.type_from_missing_module => |r| {
2835+
node.tag = .diag_type_from_missing_module;
2836+
region = r.region;
2837+
node.data_1 = @as(u32, @bitCast(r.module_name));
2838+
node.data_2 = @as(u32, @bitCast(r.type_name));
2839+
},
28342840
.module_not_imported => |r| {
28352841
node.tag = .diag_module_not_imported;
28362842
region = r.region;
@@ -3083,6 +3089,11 @@ pub fn getDiagnostic(store: *const NodeStore, diagnostic: CIR.Diagnostic.Idx) CI
30833089
.type_name = @as(base.Ident.Idx, @bitCast(node.data_2)),
30843090
.region = store.getRegionAt(node_idx),
30853091
} },
3092+
.diag_type_from_missing_module => return CIR.Diagnostic{ .type_from_missing_module = .{
3093+
.module_name = @as(base.Ident.Idx, @bitCast(node.data_1)),
3094+
.type_name = @as(base.Ident.Idx, @bitCast(node.data_2)),
3095+
.region = store.getRegionAt(node_idx),
3096+
} },
30863097
.diag_module_not_imported => return CIR.Diagnostic{ .module_not_imported = .{
30873098
.module_name = @as(base.Ident.Idx, @bitCast(node.data_1)),
30883099
.region = store.getRegionAt(node_idx),

0 commit comments

Comments
 (0)