@@ -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+
19051924pub 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
23802404const 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
52595312fn testResolvePeerTypes (ip : * InternPool , a : Index , b : Index , expected : Index ) ! void {
0 commit comments