Skip to content

Commit da2d98f

Browse files
Fix recursive nominal alias unification
1 parent 34d8a6e commit da2d98f

1 file changed

Lines changed: 58 additions & 0 deletions

File tree

src/postcheck/monotype/solve.zig

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,14 @@ pub const InstGraph = struct {
433433
try self.union_(left, right);
434434
return;
435435
}
436+
if (left_named.kind == .alias) {
437+
try self.unifyThroughBacking(left, left_content, right, pending);
438+
return;
439+
}
440+
if (right_named.kind == .alias) {
441+
try self.unifyThroughBacking(right, right_content, left, pending);
442+
return;
443+
}
436444
try self.unifyThroughBacking(left, left_content, right, pending);
437445
},
438446
else => try self.unifyThroughBacking(left, left_content, right, pending),
@@ -1036,3 +1044,53 @@ pub fn assertNoDuplicateTags(name_store: *const names.NameStore, tags: []const T
10361044
test "monotype solve declarations are referenced" {
10371045
std.testing.refAllDecls(@This());
10381046
}
1047+
1048+
test "recursive nominal backing can meet an alias to that nominal" {
1049+
const gpa = std.testing.allocator;
1050+
1051+
var type_store = Type.Store.init(gpa);
1052+
defer type_store.deinit();
1053+
1054+
var name_store = names.NameStore.init(gpa);
1055+
defer name_store.deinit();
1056+
1057+
var unsolved_monos = std.AutoHashMap(Type.TypeId, void).init(gpa);
1058+
defer unsolved_monos.deinit();
1059+
1060+
const graph = try InstGraph.create(gpa, &type_store, &name_store, &unsolved_monos);
1061+
defer graph.destroy();
1062+
1063+
const module_name = try name_store.internModuleName("Main");
1064+
const nominal_name = try name_store.internTypeName("Role");
1065+
const alias_name = try name_store.internTypeName("Wrapper.Role");
1066+
const nominal_type: Type.NamedType = .{ .module = .{}, .ty = @enumFromInt(3) };
1067+
const alias_type: Type.NamedType = .{ .module = .{}, .ty = @enumFromInt(4) };
1068+
const nominal_def: Type.TypeDef = .{ .module_name = module_name, .type_name = nominal_name };
1069+
const alias_def: Type.TypeDef = .{ .module_name = module_name, .type_name = alias_name };
1070+
1071+
const nominal = try graph.newNode(.{ .unresolved = .{} });
1072+
try graph.setContent(nominal, .{ .named = .{
1073+
.named_type = nominal_type,
1074+
.def = nominal_def,
1075+
.kind = .nominal,
1076+
.builtin_owner = null,
1077+
.args = try graph.arena().alloc(NodeId, 0),
1078+
.backing = .{ .node = nominal, .use = .inspectable },
1079+
} });
1080+
1081+
const alias = try graph.newNode(.{ .named = .{
1082+
.named_type = alias_type,
1083+
.def = alias_def,
1084+
.kind = .alias,
1085+
.builtin_owner = null,
1086+
.args = try graph.arena().alloc(NodeId, 0),
1087+
.backing = .{ .node = nominal, .use = .inspectable },
1088+
} });
1089+
1090+
const before_nodes = graph.nodes.items.len;
1091+
try graph.unify(nominal, alias);
1092+
1093+
try std.testing.expectEqual(before_nodes, graph.nodes.items.len);
1094+
try std.testing.expectEqual(nominal, graph.find(nominal));
1095+
try std.testing.expectEqual(alias, graph.find(alias));
1096+
}

0 commit comments

Comments
 (0)