Skip to content

Commit a4d1bde

Browse files
committed
Fix small PR feedback odds & ends
1 parent e1f4ac1 commit a4d1bde

File tree

4 files changed

+93
-31
lines changed

4 files changed

+93
-31
lines changed

src/check/canonicalize/Alias.zig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ pub const Kind = union(enum) {
4444
/// The data for a nominal alias, e.g. `Foo := [Foo(Str)]`
4545
pub const Nominal = struct {
4646
type_variables: Var.Range,
47-
recursion_variables: std.AutoHashMap(TypeVar, Ident.Idx),
4847
};
4948
/// The data for a structural alias, e.g. `Foo : { bar : Str }`
5049
pub const Structural = struct {

src/check/check_types/unify.zig

Lines changed: 81 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,7 @@ const Unifier = struct {
727727
// Unify fields
728728
switch (fields_ext) {
729729
.exactly_the_same => {
730-
// Unify exts (these will both be the empty record)
730+
// Unify exts
731731
try self.unifyGuarded(a_gathered_fields.ext, b_gathered_fields.ext);
732732

733733
// Unify shared fields
@@ -913,11 +913,10 @@ const Unifier = struct {
913913
b_fields_range: RecordFieldSafeList.Range,
914914
) PartitionedRecordFields {
915915
// First sort the fields
916-
const sort_ctx = RecordField.SortCtx{ .store = ident_store };
917916
const a_fields = scratch.gathered_fields.rangeToSlice(a_fields_range);
918-
std.mem.sort(RecordField, a_fields, sort_ctx, comptime RecordField.sortByNameAsc);
917+
std.mem.sort(RecordField, a_fields, ident_store, comptime RecordField.sortByNameAsc);
919918
const b_fields = scratch.gathered_fields.rangeToSlice(b_fields_range);
920-
std.mem.sort(RecordField, b_fields, sort_ctx, comptime RecordField.sortByNameAsc);
919+
std.mem.sort(RecordField, b_fields, ident_store, comptime RecordField.sortByNameAsc);
921920

922921
// Get the start of index of the new range
923922
const a_fields_start: RecordFieldSafeList.Idx = @enumFromInt(scratch.only_in_a_fields.len());
@@ -1130,7 +1129,7 @@ const Unifier = struct {
11301129
// Unify tags
11311130
switch (tags_ext) {
11321131
.exactly_the_same => {
1133-
// Unify exts (these will both be the empty tag_union)
1132+
// Unify exts
11341133
try self.unifyGuarded(a_gathered_tags.ext, b_gathered_tags.ext);
11351134

11361135
// Unify shared tags
@@ -1316,11 +1315,10 @@ const Unifier = struct {
13161315
b_tags_range: TagSafeList.Range,
13171316
) PartitionedTags {
13181317
// First sort the tags
1319-
const sort_ctx = Tag.SortCtx{ .store = ident_store };
13201318
const a_tags = scratch.gathered_tags.rangeToSlice(a_tags_range);
1321-
std.mem.sort(Tag, a_tags, sort_ctx, comptime Tag.sortByNameAsc);
1319+
std.mem.sort(Tag, a_tags, ident_store, comptime Tag.sortByNameAsc);
13221320
const b_tags = scratch.gathered_tags.rangeToSlice(b_tags_range);
1323-
std.mem.sort(Tag, b_tags, sort_ctx, comptime Tag.sortByNameAsc);
1321+
std.mem.sort(Tag, b_tags, ident_store, comptime Tag.sortByNameAsc);
13241322

13251323
// Get the start of index of the new range
13261324
const a_tags_start: TagSafeList.Idx = @enumFromInt(scratch.only_in_a_tags.len());
@@ -2849,6 +2847,41 @@ test "unify - closed record mismatch on diff fields (fail)" {
28492847

28502848
// unification - structure/structure - records open
28512849

2850+
test "unify - identital open records" {
2851+
const gpa = std.testing.allocator;
2852+
var env = TestEnv.init(gpa);
2853+
defer env.deinit();
2854+
2855+
const str = env.types_store.freshFromContent(Content{ .structure = .str });
2856+
2857+
const field_shared = env.mkRecordField("x", str);
2858+
2859+
const a_rec_data = env.mkRecordOpen(&[_]RecordField{field_shared});
2860+
const a = env.types_store.freshFromContent(a_rec_data.content);
2861+
const b_rec_data = env.mkRecordOpen(&[_]RecordField{field_shared});
2862+
const b = env.types_store.freshFromContent(b_rec_data.content);
2863+
2864+
const result = unify(&env.types_store, &env.scratch, a, b);
2865+
2866+
try std.testing.expectEqual(.ok, result);
2867+
try std.testing.expectEqual(Slot{ .redirect = b }, env.types_store.getSlot(a));
2868+
2869+
// check that the update var at b is correct
2870+
2871+
const b_record = try TestEnv.getRecordOrErr(try env.getDescForRootVar(b));
2872+
try std.testing.expectEqual(1, b_record.fields.len());
2873+
const b_record_fields = env.types_store.getRecordFieldsSlice(b_record.fields);
2874+
try std.testing.expectEqual(field_shared.name, b_record_fields.items(.name)[0]);
2875+
try std.testing.expectEqual(field_shared.var_, b_record_fields.items(.var_)[0]);
2876+
2877+
const b_ext = env.types_store.resolveVar(b_record.ext).desc.content;
2878+
try std.testing.expectEqual(Content{ .flex_var = null }, b_ext);
2879+
2880+
// check that fresh vars are correct
2881+
2882+
try std.testing.expectEqual(0, env.scratch.fresh_vars.len());
2883+
}
2884+
28522885
test "unify - open record a extends b" {
28532886
const gpa = std.testing.allocator;
28542887
var env = TestEnv.init(gpa);
@@ -3281,6 +3314,46 @@ test "unify - closed tag_unions with diff args (fail)" {
32813314

32823315
// unification - structure/structure - tag unions open
32833316

3317+
test "unify - identital open tag unions" {
3318+
const gpa = std.testing.allocator;
3319+
var env = TestEnv.init(gpa);
3320+
defer env.deinit();
3321+
3322+
const str = env.types_store.freshFromContent(Content{ .structure = .str });
3323+
3324+
const tag_shared = env.mkTag("Shared", &[_]Var{ str, str });
3325+
3326+
const tag_union_a = env.mkTagUnionOpen(&[_]Tag{tag_shared});
3327+
const a = env.types_store.freshFromContent(tag_union_a.content);
3328+
3329+
const tag_union_b = env.mkTagUnionOpen(&[_]Tag{tag_shared});
3330+
const b = env.types_store.freshFromContent(tag_union_b.content);
3331+
3332+
const result = unify(&env.types_store, &env.scratch, a, b);
3333+
3334+
try std.testing.expectEqual(.ok, result);
3335+
try std.testing.expectEqual(Slot{ .redirect = b }, env.types_store.getSlot(a));
3336+
3337+
// check that the update var at b is correct
3338+
3339+
const b_tag_union = try TestEnv.getTagUnionOrErr(try env.getDescForRootVar(b));
3340+
try std.testing.expectEqual(1, b_tag_union.tags.len());
3341+
3342+
const b_tags = env.types_store.tags.rangeToSlice(b_tag_union.tags);
3343+
const b_tags_names = b_tags.items(.name);
3344+
const b_tags_args = b_tags.items(.args);
3345+
try std.testing.expectEqual(1, b_tags.len);
3346+
try std.testing.expectEqual(tag_shared.name, b_tags_names[0]);
3347+
try std.testing.expectEqual(tag_shared.args, b_tags_args[0]);
3348+
3349+
const b_ext = env.types_store.resolveVar(b_tag_union.ext).desc.content;
3350+
try std.testing.expectEqual(Content{ .flex_var = null }, b_ext);
3351+
3352+
// check that fresh vars are correct
3353+
3354+
try std.testing.expectEqual(0, env.scratch.fresh_vars.len());
3355+
}
3356+
32843357
test "unify - open tag union a extends b" {
32853358
const gpa = std.testing.allocator;
32863359
var env = TestEnv.init(gpa);

src/check/resolve_imports/IR.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,14 @@ pub const DeclarationTag = union(enum) {
7878
Destructure: collections.SafeList(DestructureDef).Idx,
7979
MutualRecursion: struct {
8080
length: u16,
81-
cycle_mark: IllegalCycleMark,
81+
cycle_mark: InfiniteMutualRecursion,
8282
},
8383

8484
pub const List = collections.SafeList(@This());
8585
};
8686

8787
/// Marks whether a recursive let-cycle was determined to be illegal during solving.
88-
pub const IllegalCycleMark = ?TypeVar;
88+
pub const InfiniteMutualRecursion = ?TypeVar;
8989

9090
/// todo
9191
pub const FunctionDef = struct {

src/types/types.zig

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ pub const Mark = enum(u32) {
6060
none = 2,
6161
_,
6262

63-
/// Get the lowest rank
63+
/// Get the next mark
6464
pub fn next(self: Self) Self {
6565
return self + 1;
6666
}
@@ -69,11 +69,6 @@ pub const Mark = enum(u32) {
6969
// content //
7070

7171
/// Represents what the a type *is*
72-
///
73-
/// Numbers are special cased here. This means that when constraints, types
74-
/// like `Num(Int(Unsigned64))` should be reperesntsed as it's specific
75-
/// `flat_type.num` *not* as `flat_type.apply`. See 'Num' struct for additional
76-
/// details
7772
pub const Content = union(enum) {
7873
const Self = @This();
7974

@@ -175,10 +170,10 @@ pub const Tuple = struct {
175170

176171
/// Represents number
177172
///
178-
/// Numbers could be representsed by `type_apply` and phantom types, but
179-
/// that ends up being inefficient because every number type requires
180-
/// multiple different type entries. By special casing them here we can
181-
/// ensure that they have more compact representations
173+
/// Numbers are special-cased here. We represent them to the Roc programmer
174+
/// as opaque types with phantom type variables, but since they come up so
175+
/// often, we unify that representation into a special (much more compact)
176+
/// representation which saves a lot of memory.
182177
pub const Num = union(enum) {
183178
const Self = @This();
184179

@@ -287,14 +282,12 @@ pub const RecordField = struct {
287282

288283
/// The name of the field
289284
name: Ident.Idx,
285+
/// The type of the field's value
290286
var_: Var,
291287

292-
/// The context need by sortByFieldNameAsc
293-
pub const SortCtx = struct { store: *const Ident.Store };
294-
295288
/// A function to be passed into std.mem.sort to sort fields by name
296-
pub fn sortByNameAsc(ctx: SortCtx, a: Self, b: Self) bool {
297-
return Self.orderByName(ctx.store, a, b) == .lt;
289+
pub fn sortByNameAsc(ident_store: *const Ident.Store, a: Self, b: Self) bool {
290+
return Self.orderByName(ident_store, a, b) == .lt;
298291
}
299292

300293
/// Get the ordering of how a compares to b
@@ -341,12 +334,9 @@ pub const Tag = struct {
341334

342335
const Self = @This();
343336

344-
/// The context need by sortByFieldNameAsc
345-
pub const SortCtx = struct { store: *const Ident.Store };
346-
347337
/// A function to be passed into std.mem.sort to sort fields by name
348-
pub fn sortByNameAsc(ctx: SortCtx, a: Self, b: Self) bool {
349-
return Self.orderByName(ctx.store, a, b) == .lt;
338+
pub fn sortByNameAsc(ident_store: *const Ident.Store, a: Self, b: Self) bool {
339+
return Self.orderByName(ident_store, a, b) == .lt;
350340
}
351341

352342
/// Get the ordering of how a compares to b

0 commit comments

Comments
 (0)