Skip to content

Commit 12147d0

Browse files
Resolve peer types: error set and interned type
1 parent 22fc237 commit 12147d0

1 file changed

Lines changed: 66 additions & 13 deletions

File tree

src/analyser/InternPool.zig

Lines changed: 66 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1902,6 +1902,25 @@ fn coerceInt(
19021902
}
19031903
}
19041904

1905+
fn resolvePeerPayloadType(ip: *InternPool, gpa: Allocator, ty: Index, err_set_ty: *Index) !?Index {
1906+
const tag = ip.zigTypeTag(ty) orelse return ty;
1907+
const payload, const error_set = switch (tag) {
1908+
.error_set => .{ null, ty },
1909+
.error_union => blk: {
1910+
const info = ip.indexToKey(ty).error_union_type;
1911+
break :blk .{ info.payload_type, info.error_set_type };
1912+
},
1913+
else => .{ ty, null },
1914+
};
1915+
if (error_set) |e| {
1916+
switch (err_set_ty.*) {
1917+
.none => err_set_ty.* = e,
1918+
else => err_set_ty.* = try ip.errorSetMerge(gpa, err_set_ty.*, e),
1919+
}
1920+
}
1921+
return payload;
1922+
}
1923+
19051924
pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, target: std.Target) Allocator.Error!Index {
19061925
if (std.debug.runtime_safety) {
19071926
for (types) |ty| {
@@ -1919,16 +1938,24 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t
19191938
defer arena_allocator.deinit();
19201939
const arena = arena_allocator.allocator();
19211940

1922-
var chosen = types[0];
19231941
// If this is non-null then it does the following thing, depending on the chosen zigTypeTag().
19241942
// * ErrorSet: this is an override
19251943
// * ErrorUnion: this is an override of the error set only
19261944
// * other: at the end we make an ErrorUnion with the other thing and this
1927-
const err_set_ty: Index = Index.none;
1945+
var err_set_ty: Index = .none;
1946+
1947+
var chosen = for (types) |ty| {
1948+
break try ip.resolvePeerPayloadType(gpa, ty, &err_set_ty) orelse continue;
1949+
} else {
1950+
return err_set_ty;
1951+
};
1952+
19281953
var any_are_null = false;
19291954
var seen_const = false;
19301955
var convert_to_slice = false;
1931-
for (types[1..]) |candidate| {
1956+
for (types[1..]) |ty| {
1957+
const candidate = try ip.resolvePeerPayloadType(gpa, ty, &err_set_ty) orelse continue;
1958+
19321959
if (candidate == chosen) continue;
19331960

19341961
const candidate_key: Key = ip.indexToKey(candidate);
@@ -2200,8 +2227,8 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t
22002227
.pointer_type => |chosen_ptr_info| {
22012228
seen_const = seen_const or chosen_ptr_info.flags.is_const or candidate_info.flags.is_const;
22022229

2203-
// *[N]T to ?![*]T
2204-
// *[N]T to ?![]T
2230+
// *[N]T to ?[*]T
2231+
// *[N]T to ?[]T
22052232
if (candidate_info.flags.size == .one and
22062233
ip.indexToKey(candidate_info.elem_type) == .array_type and
22072234
(chosen_ptr_info.flags.size == .many or chosen_ptr_info.flags.size == .slice))
@@ -2262,13 +2289,6 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t
22622289
},
22632290
else => {},
22642291
},
2265-
.error_set_type => switch (chosen_key) {
2266-
.error_set_type => {
2267-
chosen = try ip.errorSetMerge(gpa, chosen, candidate);
2268-
continue;
2269-
},
2270-
else => {},
2271-
},
22722292
else => {},
22732293
}
22742294

@@ -2374,7 +2394,11 @@ pub fn resolvePeerTypes(ip: *InternPool, gpa: Allocator, types: []const Index, t
23742394
} });
23752395
}
23762396

2377-
return chosen;
2397+
const set_ty = if (err_set_ty != .none) err_set_ty else return chosen;
2398+
return try ip.get(gpa, .{ .error_union_type = .{
2399+
.error_set_type = set_ty,
2400+
.payload_type = chosen,
2401+
} });
23782402
}
23792403

23802404
const InMemoryCoercionResult = union(enum) {
@@ -5252,8 +5276,37 @@ test "resolvePeerTypes error sets" {
52525276
.names = try ip.getStringSlice(gpa, &.{ bar_name, foo_name }),
52535277
} });
52545278

5279+
const @"error{foo}!i32" = try ip.get(gpa, .{ .error_union_type = .{
5280+
.error_set_type = @"error{foo}",
5281+
.payload_type = .i32_type,
5282+
} });
5283+
5284+
const @"anyerror!i32" = try ip.get(gpa, .{ .error_union_type = .{
5285+
.error_set_type = .anyerror_type,
5286+
.payload_type = .i32_type,
5287+
} });
5288+
5289+
const @"error{foo,bar}!i32" = try ip.get(gpa, .{ .error_union_type = .{
5290+
.error_set_type = @"error{foo,bar}",
5291+
.payload_type = .i32_type,
5292+
} });
5293+
5294+
const @"error{bar,foo}!i32" = try ip.get(gpa, .{ .error_union_type = .{
5295+
.error_set_type = @"error{bar,foo}",
5296+
.payload_type = .i32_type,
5297+
} });
5298+
52555299
try ip.testResolvePeerTypesInOrder(@"error{foo}", @"error{bar}", @"error{foo,bar}");
52565300
try ip.testResolvePeerTypesInOrder(@"error{bar}", @"error{foo}", @"error{bar,foo}");
5301+
5302+
try ip.testResolvePeerTypes(@"error{foo}", .i32_type, @"error{foo}!i32");
5303+
try ip.testResolvePeerTypes(.anyerror_type, .i32_type, @"anyerror!i32");
5304+
5305+
try ip.testResolvePeerTypes(.anyerror_type, @"error{foo}!i32", @"anyerror!i32");
5306+
try ip.testResolvePeerTypes(@"anyerror!i32", @"error{foo}!i32", @"anyerror!i32");
5307+
5308+
try ip.testResolvePeerTypesInOrder(@"error{foo}!i32", @"error{bar}", @"error{foo,bar}!i32");
5309+
try ip.testResolvePeerTypesInOrder(@"error{bar}", @"error{foo}!i32", @"error{bar,foo}!i32");
52575310
}
52585311

52595312
fn testResolvePeerTypes(ip: *InternPool, a: Index, b: Index, expected: Index) !void {

0 commit comments

Comments
 (0)