authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-13 13:24:44-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-18 19:02:06-07:00
log684aee32209932166713462cc341fa469aad0728
treec7d90cbd2143bf022f8dc324fadf12a04364f73e
parent927f6ec8ca2234e8c4f27174359d5053da63a77d

frontend: fixes for function regressions in this branch

* Introduce InternPool.Tag.func_coerced to handle the case of a function body coerced to a new type. `InternPool.getCoerced` is now implemented for function bodies in this branch. * implement resolution of ad-hoc inferred error sets in `Sema.analyzeCall`. * fix generic_owner being set wrong for child Sema bodies of param expressions. * fix `Sema.resolveInferredErrorSetTy` when passed `anyerror`.

2 files changed, 306 insertions(+), 187 deletions(-)

src/InternPool.zig+272-179
......@@ -1670,6 +1670,9 @@ pub const Index = enum(u32) {
16701670 @"trailing.comptime_args.len": *@"data.generic_owner.data.ty.data.params_len",
16711671 trailing: struct { resolved_error_set: []Index, comptime_args: []Index },
16721672 },
1673 func_coerced: struct {
1674 data: *Tag.FuncCoerced,
1675 },
16731676 only_possible_value: DataIsIndex,
16741677 union_value: struct { data: *Key.Union },
16751678 bytes: struct { data: *Bytes },
......@@ -2192,6 +2195,9 @@ pub const Tag = enum(u8) {
21922195 /// A generic function instantiation.
21932196 /// data is extra index to `FuncInstance`.
21942197 func_instance,
2198 /// A `func_decl` or a `func_instance` that has been coerced to a different type.
2199 /// data is extra index to `FuncCoerced`.
2200 func_coerced,
21952201 /// This represents the only possible value for *some* types which have
21962202 /// only one possible value. Not all only-possible-values are encoded this way;
21972203 /// for example structs which have all comptime fields are not encoded this way.
......@@ -2298,6 +2304,7 @@ pub const Tag = enum(u8) {
22982304 .extern_func => ExternFunc,
22992305 .func_decl => FuncDecl,
23002306 .func_instance => FuncInstance,
2307 .func_coerced => FuncCoerced,
23012308 .only_possible_value => unreachable,
23022309 .union_value => Union,
23032310 .bytes => Bytes,
......@@ -2364,6 +2371,11 @@ pub const Tag = enum(u8) {
23642371 generic_owner: Index,
23652372 };
23662373
2374 pub const FuncCoerced = struct {
2375 ty: Index,
2376 func: Index,
2377 };
2378
23672379 /// Trailing:
23682380 /// 0. name: NullTerminatedString for each names_len
23692381 pub const ErrorSet = struct {
......@@ -3205,6 +3217,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
32053217 .extern_func => .{ .extern_func = ip.extraData(Tag.ExternFunc, data) },
32063218 .func_instance => .{ .func = ip.extraFuncInstance(data) },
32073219 .func_decl => .{ .func = ip.extraFuncDecl(data) },
3220 .func_coerced => .{ .func = ip.extraFuncCoerced(data) },
32083221 .only_possible_value => {
32093222 const ty = @as(Index, @enumFromInt(data));
32103223 const ty_item = ip.items.get(@intFromEnum(ty));
......@@ -3397,6 +3410,18 @@ fn extraFuncInstance(ip: *const InternPool, extra_index: u32) Key.Func {
33973410 };
33983411}
33993412
3413fn extraFuncCoerced(ip: *const InternPool, extra_index: u32) Key.Func {
3414 const func_coerced = ip.extraData(Tag.FuncCoerced, extra_index);
3415 const sub_item = ip.items.get(@intFromEnum(func_coerced.func));
3416 var func: Key.Func = switch (sub_item.tag) {
3417 .func_instance => ip.extraFuncInstance(sub_item.data),
3418 .func_decl => ip.extraFuncDecl(sub_item.data),
3419 else => unreachable,
3420 };
3421 func.ty = func_coerced.ty;
3422 return func;
3423}
3424
34003425fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key {
34013426 const enum_explicit = ip.extraDataTrail(EnumExplicit, data);
34023427 const names = @as(
......@@ -5480,210 +5505,226 @@ pub fn sliceLen(ip: *const InternPool, i: Index) Index {
54805505pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index {
54815506 const old_ty = ip.typeOf(val);
54825507 if (old_ty == new_ty) return val;
5508
5509 const tags = ip.items.items(.tag);
5510
54835511 switch (val) {
54845512 .undef => return ip.get(gpa, .{ .undef = new_ty }),
5485 .null_value => if (ip.isOptionalType(new_ty))
5486 return ip.get(gpa, .{ .opt = .{
5513 .null_value => {
5514 if (ip.isOptionalType(new_ty)) return ip.get(gpa, .{ .opt = .{
54875515 .ty = new_ty,
54885516 .val = .none,
5489 } })
5490 else if (ip.isPointerType(new_ty))
5491 return ip.get(gpa, .{ .ptr = .{
5517 } });
5518
5519 if (ip.isPointerType(new_ty)) return ip.get(gpa, .{ .ptr = .{
54925520 .ty = new_ty,
54935521 .addr = .{ .int = .zero_usize },
54945522 .len = switch (ip.indexToKey(new_ty).ptr_type.flags.size) {
54955523 .One, .Many, .C => .none,
54965524 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),
54975525 },
5498 } }),
5499 else => switch (ip.indexToKey(val)) {
5500 .undef => return ip.get(gpa, .{ .undef = new_ty }),
5501 .extern_func => |extern_func| if (ip.isFunctionType(new_ty))
5502 return ip.get(gpa, .{ .extern_func = .{
5503 .ty = new_ty,
5504 .decl = extern_func.decl,
5505 .lib_name = extern_func.lib_name,
5506 } }),
5507
5508 .func => |func| {
5509 if (func.generic_owner == .none) {
5510 @panic("TODO");
5511 } else {
5512 @panic("TODO");
5526 } });
5527 },
5528 else => switch (tags[@intFromEnum(val)]) {
5529 .func_decl => return getCoercedFuncDecl(ip, gpa, val, new_ty),
5530 .func_instance => return getCoercedFuncInstance(ip, gpa, val, new_ty),
5531 .func_coerced => {
5532 const extra_index = ip.items.items(.data)[@intFromEnum(val)];
5533 const func: Index = @enumFromInt(
5534 ip.extra.items[extra_index + std.meta.fieldIndex(Tag.FuncCoerced, "func").?],
5535 );
5536 switch (tags[@intFromEnum(func)]) {
5537 .func_decl => return getCoercedFuncDecl(ip, gpa, val, new_ty),
5538 .func_instance => return getCoercedFuncInstance(ip, gpa, val, new_ty),
5539 else => unreachable,
55135540 }
55145541 },
5542 else => {},
5543 },
5544 }
55155545
5516 .int => |int| switch (ip.indexToKey(new_ty)) {
5517 .enum_type => |enum_type| return ip.get(gpa, .{ .enum_tag = .{
5518 .ty = new_ty,
5519 .int = try ip.getCoerced(gpa, val, enum_type.tag_ty),
5520 } }),
5521 .ptr_type => return ip.get(gpa, .{ .ptr = .{
5546 switch (ip.indexToKey(val)) {
5547 .undef => return ip.get(gpa, .{ .undef = new_ty }),
5548 .extern_func => |extern_func| if (ip.isFunctionType(new_ty))
5549 return ip.get(gpa, .{ .extern_func = .{
5550 .ty = new_ty,
5551 .decl = extern_func.decl,
5552 .lib_name = extern_func.lib_name,
5553 } }),
5554
5555 .func => unreachable,
5556
5557 .int => |int| switch (ip.indexToKey(new_ty)) {
5558 .enum_type => |enum_type| return ip.get(gpa, .{ .enum_tag = .{
5559 .ty = new_ty,
5560 .int = try ip.getCoerced(gpa, val, enum_type.tag_ty),
5561 } }),
5562 .ptr_type => return ip.get(gpa, .{ .ptr = .{
5563 .ty = new_ty,
5564 .addr = .{ .int = try ip.getCoerced(gpa, val, .usize_type) },
5565 } }),
5566 else => if (ip.isIntegerType(new_ty))
5567 return getCoercedInts(ip, gpa, int, new_ty),
5568 },
5569 .float => |float| switch (ip.indexToKey(new_ty)) {
5570 .simple_type => |simple| switch (simple) {
5571 .f16,
5572 .f32,
5573 .f64,
5574 .f80,
5575 .f128,
5576 .c_longdouble,
5577 .comptime_float,
5578 => return ip.get(gpa, .{ .float = .{
55225579 .ty = new_ty,
5523 .addr = .{ .int = try ip.getCoerced(gpa, val, .usize_type) },
5580 .storage = float.storage,
55245581 } }),
5525 else => if (ip.isIntegerType(new_ty))
5526 return getCoercedInts(ip, gpa, int, new_ty),
5527 },
5528 .float => |float| switch (ip.indexToKey(new_ty)) {
5529 .simple_type => |simple| switch (simple) {
5530 .f16,
5531 .f32,
5532 .f64,
5533 .f80,
5534 .f128,
5535 .c_longdouble,
5536 .comptime_float,
5537 => return ip.get(gpa, .{ .float = .{
5538 .ty = new_ty,
5539 .storage = float.storage,
5540 } }),
5541 else => {},
5542 },
55435582 else => {},
55445583 },
5545 .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty))
5546 return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty),
5547 .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) {
5548 .enum_type => |enum_type| {
5549 const index = enum_type.nameIndex(ip, enum_literal).?;
5550 return ip.get(gpa, .{ .enum_tag = .{
5551 .ty = new_ty,
5552 .int = if (enum_type.values.len != 0)
5553 enum_type.values[index]
5554 else
5555 try ip.get(gpa, .{ .int = .{
5556 .ty = enum_type.tag_ty,
5557 .storage = .{ .u64 = index },
5558 } }),
5559 } });
5560 },
5584 else => {},
5585 },
5586 .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty))
5587 return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty),
5588 .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) {
5589 .enum_type => |enum_type| {
5590 const index = enum_type.nameIndex(ip, enum_literal).?;
5591 return ip.get(gpa, .{ .enum_tag = .{
5592 .ty = new_ty,
5593 .int = if (enum_type.values.len != 0)
5594 enum_type.values[index]
5595 else
5596 try ip.get(gpa, .{ .int = .{
5597 .ty = enum_type.tag_ty,
5598 .storage = .{ .u64 = index },
5599 } }),
5600 } });
5601 },
5602 else => {},
5603 },
5604 .ptr => |ptr| if (ip.isPointerType(new_ty))
5605 return ip.get(gpa, .{ .ptr = .{
5606 .ty = new_ty,
5607 .addr = ptr.addr,
5608 .len = ptr.len,
5609 } })
5610 else if (ip.isIntegerType(new_ty))
5611 switch (ptr.addr) {
5612 .int => |int| return ip.getCoerced(gpa, int, new_ty),
55615613 else => {},
55625614 },
5563 .ptr => |ptr| if (ip.isPointerType(new_ty))
5564 return ip.get(gpa, .{ .ptr = .{
5615 .opt => |opt| switch (ip.indexToKey(new_ty)) {
5616 .ptr_type => |ptr_type| return switch (opt.val) {
5617 .none => try ip.get(gpa, .{ .ptr = .{
55655618 .ty = new_ty,
5566 .addr = ptr.addr,
5567 .len = ptr.len,
5568 } })
5569 else if (ip.isIntegerType(new_ty))
5570 switch (ptr.addr) {
5571 .int => |int| return ip.getCoerced(gpa, int, new_ty),
5572 else => {},
5573 },
5574 .opt => |opt| switch (ip.indexToKey(new_ty)) {
5575 .ptr_type => |ptr_type| return switch (opt.val) {
5576 .none => try ip.get(gpa, .{ .ptr = .{
5577 .ty = new_ty,
5578 .addr = .{ .int = .zero_usize },
5579 .len = switch (ptr_type.flags.size) {
5580 .One, .Many, .C => .none,
5581 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),
5582 },
5583 } }),
5584 else => |payload| try ip.getCoerced(gpa, payload, new_ty),
5585 },
5586 .opt_type => |child_type| return try ip.get(gpa, .{ .opt = .{
5587 .ty = new_ty,
5588 .val = switch (opt.val) {
5589 .none => .none,
5590 else => try ip.getCoerced(gpa, opt.val, child_type),
5619 .addr = .{ .int = .zero_usize },
5620 .len = switch (ptr_type.flags.size) {
5621 .One, .Many, .C => .none,
5622 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),
55915623 },
55925624 } }),
5593 else => {},
5625 else => |payload| try ip.getCoerced(gpa, payload, new_ty),
55945626 },
5595 .err => |err| if (ip.isErrorSetType(new_ty))
5596 return ip.get(gpa, .{ .err = .{
5597 .ty = new_ty,
5598 .name = err.name,
5599 } })
5600 else if (ip.isErrorUnionType(new_ty))
5601 return ip.get(gpa, .{ .error_union = .{
5602 .ty = new_ty,
5603 .val = .{ .err_name = err.name },
5604 } }),
5605 .error_union => |error_union| if (ip.isErrorUnionType(new_ty))
5606 return ip.get(gpa, .{ .error_union = .{
5607 .ty = new_ty,
5608 .val = error_union.val,
5609 } }),
5610 .aggregate => |aggregate| {
5611 const new_len = @as(usize, @intCast(ip.aggregateTypeLen(new_ty)));
5612 direct: {
5613 const old_ty_child = switch (ip.indexToKey(old_ty)) {
5614 inline .array_type, .vector_type => |seq_type| seq_type.child,
5615 .anon_struct_type, .struct_type => break :direct,
5616 else => unreachable,
5617 };
5618 const new_ty_child = switch (ip.indexToKey(new_ty)) {
5619 inline .array_type, .vector_type => |seq_type| seq_type.child,
5620 .anon_struct_type, .struct_type => break :direct,
5621 else => unreachable,
5622 };
5623 if (old_ty_child != new_ty_child) break :direct;
5624 // TODO: write something like getCoercedInts to avoid needing to dupe here
5625 switch (aggregate.storage) {
5626 .bytes => |bytes| {
5627 const bytes_copy = try gpa.dupe(u8, bytes[0..new_len]);
5628 defer gpa.free(bytes_copy);
5629 return ip.get(gpa, .{ .aggregate = .{
5630 .ty = new_ty,
5631 .storage = .{ .bytes = bytes_copy },
5632 } });
5633 },
5634 .elems => |elems| {
5635 const elems_copy = try gpa.dupe(InternPool.Index, elems[0..new_len]);
5636 defer gpa.free(elems_copy);
5637 return ip.get(gpa, .{ .aggregate = .{
5638 .ty = new_ty,
5639 .storage = .{ .elems = elems_copy },
5640 } });
5641 },
5642 .repeated_elem => |elem| {
5643 return ip.get(gpa, .{ .aggregate = .{
5644 .ty = new_ty,
5645 .storage = .{ .repeated_elem = elem },
5646 } });
5647 },
5648 }
5649 }
5650 // Direct approach failed - we must recursively coerce elems
5651 const agg_elems = try gpa.alloc(InternPool.Index, new_len);
5652 defer gpa.free(agg_elems);
5653 // First, fill the vector with the uncoerced elements. We do this to avoid key
5654 // lifetime issues, since it'll allow us to avoid referencing `aggregate` after we
5655 // begin interning elems.
5627 .opt_type => |child_type| return try ip.get(gpa, .{ .opt = .{
5628 .ty = new_ty,
5629 .val = switch (opt.val) {
5630 .none => .none,
5631 else => try ip.getCoerced(gpa, opt.val, child_type),
5632 },
5633 } }),
5634 else => {},
5635 },
5636 .err => |err| if (ip.isErrorSetType(new_ty))
5637 return ip.get(gpa, .{ .err = .{
5638 .ty = new_ty,
5639 .name = err.name,
5640 } })
5641 else if (ip.isErrorUnionType(new_ty))
5642 return ip.get(gpa, .{ .error_union = .{
5643 .ty = new_ty,
5644 .val = .{ .err_name = err.name },
5645 } }),
5646 .error_union => |error_union| if (ip.isErrorUnionType(new_ty))
5647 return ip.get(gpa, .{ .error_union = .{
5648 .ty = new_ty,
5649 .val = error_union.val,
5650 } }),
5651 .aggregate => |aggregate| {
5652 const new_len = @as(usize, @intCast(ip.aggregateTypeLen(new_ty)));
5653 direct: {
5654 const old_ty_child = switch (ip.indexToKey(old_ty)) {
5655 inline .array_type, .vector_type => |seq_type| seq_type.child,
5656 .anon_struct_type, .struct_type => break :direct,
5657 else => unreachable,
5658 };
5659 const new_ty_child = switch (ip.indexToKey(new_ty)) {
5660 inline .array_type, .vector_type => |seq_type| seq_type.child,
5661 .anon_struct_type, .struct_type => break :direct,
5662 else => unreachable,
5663 };
5664 if (old_ty_child != new_ty_child) break :direct;
5665 // TODO: write something like getCoercedInts to avoid needing to dupe here
56565666 switch (aggregate.storage) {
5657 .bytes => {
5658 // We have to intern each value here, so unfortunately we can't easily avoid
5659 // the repeated indexToKey calls.
5660 for (agg_elems, 0..) |*elem, i| {
5661 const x = ip.indexToKey(val).aggregate.storage.bytes[i];
5662 elem.* = try ip.get(gpa, .{ .int = .{
5663 .ty = .u8_type,
5664 .storage = .{ .u64 = x },
5665 } });
5666 }
5667 .bytes => |bytes| {
5668 const bytes_copy = try gpa.dupe(u8, bytes[0..new_len]);
5669 defer gpa.free(bytes_copy);
5670 return ip.get(gpa, .{ .aggregate = .{
5671 .ty = new_ty,
5672 .storage = .{ .bytes = bytes_copy },
5673 } });
5674 },
5675 .elems => |elems| {
5676 const elems_copy = try gpa.dupe(InternPool.Index, elems[0..new_len]);
5677 defer gpa.free(elems_copy);
5678 return ip.get(gpa, .{ .aggregate = .{
5679 .ty = new_ty,
5680 .storage = .{ .elems = elems_copy },
5681 } });
5682 },
5683 .repeated_elem => |elem| {
5684 return ip.get(gpa, .{ .aggregate = .{
5685 .ty = new_ty,
5686 .storage = .{ .repeated_elem = elem },
5687 } });
56675688 },
5668 .elems => |elems| @memcpy(agg_elems, elems[0..new_len]),
5669 .repeated_elem => |elem| @memset(agg_elems, elem),
5670 }
5671 // Now, coerce each element to its new type.
5672 for (agg_elems, 0..) |*elem, i| {
5673 const new_elem_ty = switch (ip.indexToKey(new_ty)) {
5674 inline .array_type, .vector_type => |seq_type| seq_type.child,
5675 .anon_struct_type => |anon_struct_type| anon_struct_type.types[i],
5676 .struct_type => |struct_type| ip.structPtr(struct_type.index.unwrap().?)
5677 .fields.values()[i].ty.toIntern(),
5678 else => unreachable,
5679 };
5680 elem.* = try ip.getCoerced(gpa, elem.*, new_elem_ty);
56815689 }
5682 return ip.get(gpa, .{ .aggregate = .{ .ty = new_ty, .storage = .{ .elems = agg_elems } } });
5683 },
5684 else => {},
5690 }
5691 // Direct approach failed - we must recursively coerce elems
5692 const agg_elems = try gpa.alloc(InternPool.Index, new_len);
5693 defer gpa.free(agg_elems);
5694 // First, fill the vector with the uncoerced elements. We do this to avoid key
5695 // lifetime issues, since it'll allow us to avoid referencing `aggregate` after we
5696 // begin interning elems.
5697 switch (aggregate.storage) {
5698 .bytes => {
5699 // We have to intern each value here, so unfortunately we can't easily avoid
5700 // the repeated indexToKey calls.
5701 for (agg_elems, 0..) |*elem, i| {
5702 const x = ip.indexToKey(val).aggregate.storage.bytes[i];
5703 elem.* = try ip.get(gpa, .{ .int = .{
5704 .ty = .u8_type,
5705 .storage = .{ .u64 = x },
5706 } });
5707 }
5708 },
5709 .elems => |elems| @memcpy(agg_elems, elems[0..new_len]),
5710 .repeated_elem => |elem| @memset(agg_elems, elem),
5711 }
5712 // Now, coerce each element to its new type.
5713 for (agg_elems, 0..) |*elem, i| {
5714 const new_elem_ty = switch (ip.indexToKey(new_ty)) {
5715 inline .array_type, .vector_type => |seq_type| seq_type.child,
5716 .anon_struct_type => |anon_struct_type| anon_struct_type.types[i],
5717 .struct_type => |struct_type| ip.structPtr(struct_type.index.unwrap().?)
5718 .fields.values()[i].ty.toIntern(),
5719 else => unreachable,
5720 };
5721 elem.* = try ip.getCoerced(gpa, elem.*, new_elem_ty);
5722 }
5723 return ip.get(gpa, .{ .aggregate = .{ .ty = new_ty, .storage = .{ .elems = agg_elems } } });
56855724 },
5725 else => {},
56865726 }
5727
56875728 switch (ip.indexToKey(new_ty)) {
56885729 .opt_type => |child_type| switch (val) {
56895730 .null_value => return ip.get(gpa, .{ .opt = .{
......@@ -5711,6 +5752,54 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
57115752 unreachable;
57125753}
57135754
5755fn getCoercedFuncDecl(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index {
5756 const datas = ip.items.items(.data);
5757 const extra_index = datas[@intFromEnum(val)];
5758 const prev_ty: Index = @enumFromInt(
5759 ip.extra.items[extra_index + std.meta.fieldIndex(Tag.FuncDecl, "ty").?],
5760 );
5761 if (new_ty == prev_ty) return val;
5762 return getCoercedFunc(ip, gpa, val, new_ty);
5763}
5764
5765fn getCoercedFuncInstance(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index {
5766 const datas = ip.items.items(.data);
5767 const extra_index = datas[@intFromEnum(val)];
5768 const prev_ty: Index = @enumFromInt(
5769 ip.extra.items[extra_index + std.meta.fieldIndex(Tag.FuncInstance, "ty").?],
5770 );
5771 if (new_ty == prev_ty) return val;
5772 return getCoercedFunc(ip, gpa, val, new_ty);
5773}
5774
5775fn getCoercedFunc(ip: *InternPool, gpa: Allocator, func: Index, ty: Index) Allocator.Error!Index {
5776 const prev_extra_len = ip.extra.items.len;
5777 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Tag.FuncCoerced).Struct.fields.len);
5778 try ip.items.ensureUnusedCapacity(gpa, 1);
5779 try ip.map.ensureUnusedCapacity(gpa, 1);
5780
5781 const extra_index = ip.addExtraAssumeCapacity(Tag.FuncCoerced{
5782 .ty = ty,
5783 .func = func,
5784 });
5785
5786 const adapter: KeyAdapter = .{ .intern_pool = ip };
5787 const gop = ip.map.getOrPutAssumeCapacityAdapted(Key{
5788 .func = extraFuncCoerced(ip, extra_index),
5789 }, adapter);
5790
5791 if (gop.found_existing) {
5792 ip.extra.items.len = prev_extra_len;
5793 return @enumFromInt(gop.index);
5794 }
5795
5796 ip.items.appendAssumeCapacity(.{
5797 .tag = .func_coerced,
5798 .data = extra_index,
5799 });
5800 return @enumFromInt(ip.items.len - 1);
5801}
5802
57145803/// Asserts `val` has an integer type.
57155804/// Assumes `new_ty` is an integer type.
57165805pub fn getCoercedInts(ip: *InternPool, gpa: Allocator, int: Key.Int, new_ty: Index) Allocator.Error!Index {
......@@ -6025,6 +6114,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
60256114 break :b @sizeOf(Tag.FuncInstance) + @sizeOf(Index) * params_len +
60266115 @sizeOf(Module.Decl);
60276116 },
6117 .func_coerced => @sizeOf(Tag.FuncCoerced),
60286118 .only_possible_value => 0,
60296119 .union_value => @sizeOf(Key.Union),
60306120
......@@ -6131,6 +6221,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
61316221 .extern_func,
61326222 .func_decl,
61336223 .func_instance,
6224 .func_coerced,
61346225 .union_value,
61356226 .memoized_call,
61366227 => try w.print("{d}", .{data}),
......@@ -6471,7 +6562,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
64716562 .undef,
64726563 .opt_null,
64736564 .only_possible_value,
6474 => @as(Index, @enumFromInt(ip.items.items(.data)[@intFromEnum(index)])),
6565 => @enumFromInt(ip.items.items(.data)[@intFromEnum(index)]),
64756566
64766567 .simple_value => unreachable, // handled via Index above
64776568
......@@ -6497,6 +6588,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
64976588 .extern_func,
64986589 .func_decl,
64996590 .func_instance,
6591 .func_coerced,
65006592 .union_value,
65016593 .bytes,
65026594 .aggregate,
......@@ -6504,7 +6596,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
65046596 => |t| {
65056597 const extra_index = ip.items.items(.data)[@intFromEnum(index)];
65066598 const field_index = std.meta.fieldIndex(t.Payload(), "ty").?;
6507 return @as(Index, @enumFromInt(ip.extra.items[extra_index + field_index]));
6599 return @enumFromInt(ip.extra.items[extra_index + field_index]);
65086600 },
65096601
65106602 .int_u8 => .u8_type,
......@@ -6850,6 +6942,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
68506942 .extern_func,
68516943 .func_decl,
68526944 .func_instance,
6945 .func_coerced,
68536946 .only_possible_value,
68546947 .union_value,
68556948 .bytes,
......@@ -6866,7 +6959,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
68666959pub fn isFuncBody(ip: *const InternPool, i: Index) bool {
68676960 assert(i != .none);
68686961 return switch (ip.items.items(.tag)[@intFromEnum(i)]) {
6869 .func_decl, .func_instance => true,
6962 .func_decl, .func_instance, .func_coerced => true,
68706963 else => false,
68716964 };
68726965}
src/Sema.zig+34-8
......@@ -7155,9 +7155,17 @@ fn analyzeCall(
71557155 break :res2 Air.internedToRef(result_transformed);
71567156 }
71577157
7158 if (sema.fn_ret_ty_ies) |ies| {
7159 _ = ies;
7160 @panic("TODO: resolve ad-hoc inferred error set");
7158 if (try sema.resolveMaybeUndefVal(result)) |result_val| {
7159 const result_interned = try result_val.intern(sema.fn_ret_ty, mod);
7160 const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned);
7161 break :res2 Air.internedToRef(result_transformed);
7162 }
7163
7164 const new_ty = try sema.resolveAdHocInferredErrorSetTy(block, call_src, sema.typeOf(result).toIntern());
7165 if (new_ty != .none) {
7166 // TODO: mutate in place the previous instruction if possible
7167 // rather than adding a bitcast instruction.
7168 break :res2 try block.addBitCast(new_ty.toType(), result);
71617169 }
71627170
71637171 break :res2 result;
......@@ -9141,11 +9149,14 @@ fn zirParam(
91419149 // Make sure any nested param instructions don't clobber our work.
91429150 const prev_params = block.params;
91439151 const prev_no_partial_func_type = sema.no_partial_func_ty;
9152 const prev_generic_owner = sema.generic_owner;
91449153 block.params = .{};
91459154 sema.no_partial_func_ty = true;
9155 sema.generic_owner = .none;
91469156 defer {
91479157 block.params = prev_params;
91489158 sema.no_partial_func_ty = prev_no_partial_func_type;
9159 sema.generic_owner = prev_generic_owner;
91499160 }
91509161
91519162 if (sema.resolveBody(block, body, inst)) |param_ty_inst| {
......@@ -34114,24 +34125,37 @@ fn resolveAdHocInferredErrorSet(
3411434125 src: LazySrcLoc,
3411534126 value: InternPool.Index,
3411634127) CompileError!InternPool.Index {
34117 const ies = sema.fn_ret_ty_ies orelse return value;
3411834128 const mod = sema.mod;
3411934129 const gpa = sema.gpa;
3412034130 const ip = &mod.intern_pool;
34121 const ty = ip.typeOf(value);
34131 const new_ty = try resolveAdHocInferredErrorSetTy(sema, block, src, ip.typeOf(value));
34132 if (new_ty == .none) return value;
34133 return ip.getCoerced(gpa, value, new_ty);
34134}
34135
34136fn resolveAdHocInferredErrorSetTy(
34137 sema: *Sema,
34138 block: *Block,
34139 src: LazySrcLoc,
34140 ty: InternPool.Index,
34141) CompileError!InternPool.Index {
34142 const ies = sema.fn_ret_ty_ies orelse return .none;
34143 const mod = sema.mod;
34144 const gpa = sema.gpa;
34145 const ip = &mod.intern_pool;
3412234146 const error_union_info = switch (ip.indexToKey(ty)) {
3412334147 .error_union_type => |x| x,
34124 else => return value,
34148 else => return .none,
3412534149 };
3412634150 if (error_union_info.error_set_type != .adhoc_inferred_error_set_type)
34127 return value;
34151 return .none;
3412834152
3412934153 try sema.resolveInferredErrorSetPtr(block, src, ies);
3413034154 const new_ty = try ip.get(gpa, .{ .error_union_type = .{
3413134155 .error_set_type = ies.resolved,
3413234156 .payload_type = error_union_info.payload_type,
3413334157 } });
34134 return ip.getCoerced(gpa, value, new_ty);
34158 return new_ty;
3413534159}
3413634160
3413734161fn resolveInferredErrorSetTy(
......@@ -34142,6 +34166,7 @@ fn resolveInferredErrorSetTy(
3414234166) CompileError!InternPool.Index {
3414334167 const mod = sema.mod;
3414434168 const ip = &mod.intern_pool;
34169 if (ty == .anyerror_type) return ty;
3414534170 switch (ip.indexToKey(ty)) {
3414634171 .error_set_type => return ty,
3414734172 .inferred_error_set_type => return sema.resolveInferredErrorSet(block, src, ty),
......@@ -35229,6 +35254,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
3522935254 .extern_func,
3523035255 .func_decl,
3523135256 .func_instance,
35257 .func_coerced,
3523235258 .only_possible_value,
3523335259 .union_value,
3523435260 .bytes,