authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-06-13 18:50:53+01:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-06-13 21:48:21+01:00
log8a92beb088c5eb890f0b662ca6e0c8d68b72fd6a
tree3acb3639945161008da3092313ed8a7eb107315e
parent588f45a0a1492711b2cd9991ba8e9137e583e513
signaturelock-open Commit is signed but in an unrecognized format.

Sema: move all in-memory coercion logic to InternPool

Previously, this logic was split between Sema.coerceValueInMemory and InternPool.getCoerced. This led to issues when trying to coerce e.g. an optional containing an aggregate, because we'd call through to InternPool's version which only recurses on itself so could not coerce aggregates. Unifying them is fairly simple, and also simplified a bit of logic in Sema. Also fixes a key lifetime bug in aggregate coercion.

2 files changed, 166 insertions(+), 238 deletions(-)

src/InternPool.zig+93
......@@ -4568,6 +4568,7 @@ pub fn sliceLen(ip: *const InternPool, i: Index) Index {
45684568/// * int <=> int
45694569/// * int <=> enum
45704570/// * enum_literal => enum
4571/// * float <=> float
45714572/// * ptr <=> ptr
45724573/// * opt ptr <=> ptr
45734574/// * opt ptr <=> opt ptr
......@@ -4579,6 +4580,7 @@ pub fn sliceLen(ip: *const InternPool, i: Index) Index {
45794580/// * error set => error union
45804581/// * payload => error union
45814582/// * fn <=> fn
4583/// * aggregate <=> aggregate (where children can also be coerced)
45824584pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index {
45834585 const old_ty = ip.typeOf(val);
45844586 if (old_ty == new_ty) return val;
......@@ -4623,6 +4625,23 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
46234625 else => if (ip.isIntegerType(new_ty))
46244626 return getCoercedInts(ip, gpa, int, new_ty),
46254627 },
4628 .float => |float| switch (ip.indexToKey(new_ty)) {
4629 .simple_type => |simple| switch (simple) {
4630 .f16,
4631 .f32,
4632 .f64,
4633 .f80,
4634 .f128,
4635 .c_longdouble,
4636 .comptime_float,
4637 => return ip.get(gpa, .{ .float = .{
4638 .ty = new_ty,
4639 .storage = float.storage,
4640 } }),
4641 else => {},
4642 },
4643 else => {},
4644 },
46264645 .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty))
46274646 return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty),
46284647 .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) {
......@@ -4688,6 +4707,80 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
46884707 .ty = new_ty,
46894708 .val = error_union.val,
46904709 } }),
4710 .aggregate => |aggregate| {
4711 const new_len = @intCast(usize, ip.aggregateTypeLen(new_ty));
4712 direct: {
4713 const old_ty_child = switch (ip.indexToKey(old_ty)) {
4714 inline .array_type, .vector_type => |seq_type| seq_type.child,
4715 .anon_struct_type, .struct_type => break :direct,
4716 else => unreachable,
4717 };
4718 const new_ty_child = switch (ip.indexToKey(new_ty)) {
4719 inline .array_type, .vector_type => |seq_type| seq_type.child,
4720 .anon_struct_type, .struct_type => break :direct,
4721 else => unreachable,
4722 };
4723 if (old_ty_child != new_ty_child) break :direct;
4724 // TODO: write something like getCoercedInts to avoid needing to dupe here
4725 switch (aggregate.storage) {
4726 .bytes => |bytes| {
4727 const bytes_copy = try gpa.dupe(u8, bytes[0..new_len]);
4728 defer gpa.free(bytes_copy);
4729 return ip.get(gpa, .{ .aggregate = .{
4730 .ty = new_ty,
4731 .storage = .{ .bytes = bytes_copy },
4732 } });
4733 },
4734 .elems => |elems| {
4735 const elems_copy = try gpa.dupe(InternPool.Index, elems[0..new_len]);
4736 defer gpa.free(elems_copy);
4737 return ip.get(gpa, .{ .aggregate = .{
4738 .ty = new_ty,
4739 .storage = .{ .elems = elems_copy },
4740 } });
4741 },
4742 .repeated_elem => |elem| {
4743 return ip.get(gpa, .{ .aggregate = .{
4744 .ty = new_ty,
4745 .storage = .{ .repeated_elem = elem },
4746 } });
4747 },
4748 }
4749 }
4750 // Direct approach failed - we must recursively coerce elems
4751 const agg_elems = try gpa.alloc(InternPool.Index, new_len);
4752 defer gpa.free(agg_elems);
4753 // First, fill the vector with the uncoerced elements. We do this to avoid key
4754 // lifetime issues, since it'll allow us to avoid referencing `aggregate` after we
4755 // begin interning elems.
4756 switch (aggregate.storage) {
4757 .bytes => {
4758 // We have to intern each value here, so unfortunately we can't easily avoid
4759 // the repeated indexToKey calls.
4760 for (agg_elems, 0..) |*elem, i| {
4761 const x = ip.indexToKey(val).aggregate.storage.bytes[i];
4762 elem.* = try ip.get(gpa, .{ .int = .{
4763 .ty = .u8_type,
4764 .storage = .{ .u64 = x },
4765 } });
4766 }
4767 },
4768 .elems => |elems| @memcpy(agg_elems, elems[0..new_len]),
4769 .repeated_elem => |elem| @memset(agg_elems, elem),
4770 }
4771 // Now, coerce each element to its new type.
4772 for (agg_elems, 0..) |*elem, i| {
4773 const new_elem_ty = switch (ip.indexToKey(new_ty)) {
4774 inline .array_type, .vector_type => |seq_type| seq_type.child,
4775 .anon_struct_type => |anon_struct_type| anon_struct_type.types[i],
4776 .struct_type => |struct_type| ip.structPtr(struct_type.index.unwrap().?)
4777 .fields.values()[i].ty.toIntern(),
4778 else => unreachable,
4779 };
4780 elem.* = try ip.getCoerced(gpa, elem.*, new_elem_ty);
4781 }
4782 return ip.get(gpa, .{ .aggregate = .{ .ty = new_ty, .storage = .{ .elems = agg_elems } } });
4783 },
46914784 else => {},
46924785 },
46934786 }
src/Sema.zig+73-238
......@@ -23069,7 +23069,7 @@ fn analyzeMinMax(
2306923069 if (std.debug.runtime_safety) {
2307023070 assert(try sema.intFitsInType(val, refined_ty, null));
2307123071 }
23072 cur_minmax = try sema.coerceInMemory(block, val, orig_ty, refined_ty, src);
23072 cur_minmax = try sema.coerceInMemory(val, refined_ty);
2307323073 }
2307423074
2307523075 break :refined refined_ty;
......@@ -26610,7 +26610,7 @@ fn coerceExtra(
2661026610 var in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src);
2661126611 if (in_memory_result == .ok) {
2661226612 if (maybe_inst_val) |val| {
26613 return sema.coerceInMemory(block, val, inst_ty, dest_ty, dest_ty_src);
26613 return sema.coerceInMemory(val, dest_ty);
2661426614 }
2661526615 try sema.requireRuntimeBlock(block, inst_src, null);
2661626616 return block.addBitCast(dest_ty, inst);
......@@ -27278,89 +27278,12 @@ fn coerceExtra(
2727827278 return sema.failWithOwnedErrorMsg(msg);
2727927279}
2728027280
27281fn coerceValueInMemory(
27282 sema: *Sema,
27283 block: *Block,
27284 val: Value,
27285 src_ty: Type,
27286 dst_ty: Type,
27287 dst_ty_src: LazySrcLoc,
27288) CompileError!Value {
27289 const mod = sema.mod;
27290 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
27291 .aggregate => |aggregate| {
27292 const dst_ty_key = mod.intern_pool.indexToKey(dst_ty.toIntern());
27293 const dest_len = try sema.usizeCast(
27294 block,
27295 dst_ty_src,
27296 mod.intern_pool.aggregateTypeLen(dst_ty.toIntern()),
27297 );
27298 direct: {
27299 const src_ty_child = switch (mod.intern_pool.indexToKey(src_ty.toIntern())) {
27300 inline .array_type, .vector_type => |seq_type| seq_type.child,
27301 .anon_struct_type, .struct_type => break :direct,
27302 else => unreachable,
27303 };
27304 const dst_ty_child = switch (dst_ty_key) {
27305 inline .array_type, .vector_type => |seq_type| seq_type.child,
27306 .anon_struct_type, .struct_type => break :direct,
27307 else => unreachable,
27308 };
27309 if (src_ty_child != dst_ty_child) break :direct;
27310 // TODO: write something like getCoercedInts to avoid needing to dupe
27311 return (try mod.intern(.{ .aggregate = .{
27312 .ty = dst_ty.toIntern(),
27313 .storage = switch (aggregate.storage) {
27314 .bytes => |bytes| .{ .bytes = try sema.arena.dupe(u8, bytes[0..dest_len]) },
27315 .elems => |elems| .{ .elems = try sema.arena.dupe(InternPool.Index, elems[0..dest_len]) },
27316 .repeated_elem => |elem| .{ .repeated_elem = elem },
27317 },
27318 } })).toValue();
27319 }
27320 const dest_elems = try sema.arena.alloc(InternPool.Index, dest_len);
27321 for (dest_elems, 0..) |*dest_elem, i| {
27322 const elem_ty = switch (dst_ty_key) {
27323 inline .array_type, .vector_type => |seq_type| seq_type.child,
27324 .anon_struct_type => |anon_struct_type| anon_struct_type.types[i],
27325 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?
27326 .fields.values()[i].ty.toIntern(),
27327 else => unreachable,
27328 };
27329 const cur_val = switch (aggregate.storage) {
27330 .bytes => |bytes| (try mod.intValue(Type.u8, bytes[i])).toIntern(),
27331 .elems => |elems| elems[i],
27332 .repeated_elem => |elem| elem,
27333 };
27334 dest_elem.* = (try sema.coerceValueInMemory(
27335 block,
27336 cur_val.toValue(),
27337 mod.intern_pool.typeOf(cur_val).toType(),
27338 elem_ty.toType(),
27339 dst_ty_src,
27340 )).toIntern();
27341 }
27342 return (try mod.intern(.{ .aggregate = .{
27343 .ty = dst_ty.toIntern(),
27344 .storage = .{ .elems = dest_elems },
27345 } })).toValue();
27346 },
27347 .float => |float| (try mod.intern(.{ .float = .{
27348 .ty = dst_ty.toIntern(),
27349 .storage = float.storage,
27350 } })).toValue(),
27351 else => try mod.getCoerced(val, dst_ty),
27352 };
27353}
27354
2735527281fn coerceInMemory(
2735627282 sema: *Sema,
27357 block: *Block,
2735827283 val: Value,
27359 src_ty: Type,
2736027284 dst_ty: Type,
27361 dst_ty_src: LazySrcLoc,
2736227285) CompileError!Air.Inst.Ref {
27363 return sema.addConstant(dst_ty, try sema.coerceValueInMemory(block, val, src_ty, dst_ty, dst_ty_src));
27286 return sema.addConstant(dst_ty, try sema.mod.getCoerced(val, dst_ty));
2736427287}
2736527288
2736627289const InMemoryCoercionResult = union(enum) {
......@@ -29820,7 +29743,7 @@ fn coerceArrayLike(
2982029743 if (in_memory_result == .ok) {
2982129744 if (try sema.resolveMaybeUndefVal(inst)) |inst_val| {
2982229745 // These types share the same comptime value representation.
29823 return sema.coerceInMemory(block, inst_val, inst_ty, dest_ty, dest_ty_src);
29746 return sema.coerceInMemory(inst_val, dest_ty);
2982429747 }
2982529748 try sema.requireRuntimeBlock(block, inst_src, null);
2982629749 return block.addBitCast(dest_ty, inst);
......@@ -31653,40 +31576,12 @@ const PeerResolveStrategy = enum {
3165331576 /// The peers must all be of the same type.
3165431577 exact,
3165531578
31656 const Reason = struct {
31657 peers: std.DynamicBitSet,
31658 fn reset(r: *Reason) void {
31659 r.peers.setRangeValue(.{ .start = 0, .end = r.peers.capacity() }, false);
31660 }
31661 };
31662
31663 fn name(s: PeerResolveStrategy) []const u8 {
31664 return switch (s) {
31665 .unknown, .exact => "exact",
31666 .error_set => "error set",
31667 .error_union => "error union",
31668 .nullable => "null",
31669 .optional => "optional",
31670 .array => "array",
31671 .vector => "vector",
31672 .c_ptr => "C pointer",
31673 .ptr => "pointer",
31674 .func => "function",
31675 .enum_or_union => "enum or union",
31676 .comptime_int => "comptime_int",
31677 .comptime_float => "comptime_float",
31678 .fixed_int => "fixed-width int",
31679 .fixed_float => "fixed-width float",
31680 .coercible_struct => "anonymous struct or tuple",
31681 };
31682 }
31683
3168431579 /// Given two strategies, find a strategy that satisfies both, if one exists. If no such
3168531580 /// strategy exists, any strategy may be returned; an error will be emitted when the caller
3168631581 /// attempts to use the strategy to resolve the type.
31687 /// Strategy `a` comes from the peers set in `reason`, while strategy `b` comes from the peer at
31688 /// index `b_peer_idx`. `reason` will be updated to reflect the reason for the new strategy.
31689 fn merge(a: PeerResolveStrategy, b: PeerResolveStrategy, reason: *Reason, b_peer_idx: usize) PeerResolveStrategy {
31582 /// Strategy `a` comes from the peer in `reason_peer`, while strategy `b` comes from the peer at
31583 /// index `b_peer_idx`. `reason_peer` is updated to reflect the reason for the new strategy.
31584 fn merge(a: PeerResolveStrategy, b: PeerResolveStrategy, reason_peer: *usize, b_peer_idx: usize) PeerResolveStrategy {
3169031585 // Our merging should be order-independent. Thus, even though the union order is arbitrary,
3169131586 // by sorting the tags and switching first on the smaller, we have half as many cases to
3169231587 // worry about (since we avoid the duplicates).
......@@ -31698,14 +31593,13 @@ const PeerResolveStrategy = enum {
3169831593 all_s0,
3169931594 all_s1,
3170031595 either,
31701 both,
3170231596 };
3170331597
3170431598 const res: struct { ReasonMethod, PeerResolveStrategy } = switch (s0) {
3170531599 .unknown => .{ .all_s1, s1 },
3170631600 .error_set => switch (s1) {
3170731601 .error_set => .{ .either, .error_set },
31708 else => .{ .both, .error_union },
31602 else => .{ .all_s0, .error_union },
3170931603 },
3171031604 .error_union => switch (s1) {
3171131605 .error_union => .{ .either, .error_union },
......@@ -31714,7 +31608,7 @@ const PeerResolveStrategy = enum {
3171431608 .nullable => switch (s1) {
3171531609 .nullable => .{ .either, .nullable },
3171631610 .c_ptr => .{ .all_s1, .c_ptr },
31717 else => .{ .both, .optional },
31611 else => .{ .all_s0, .optional },
3171831612 },
3171931613 .optional => switch (s1) {
3172031614 .optional => .{ .either, .optional },
......@@ -31772,23 +31666,17 @@ const PeerResolveStrategy = enum {
3177231666 switch (res[0]) {
3177331667 .all_s0 => {
3177431668 if (!s0_is_a) {
31775 reason.reset();
31776 reason.peers.set(b_peer_idx);
31669 reason_peer.* = b_peer_idx;
3177731670 }
3177831671 },
3177931672 .all_s1 => {
3178031673 if (s0_is_a) {
31781 reason.reset();
31782 reason.peers.set(b_peer_idx);
31674 reason_peer.* = b_peer_idx;
3178331675 }
3178431676 },
3178531677 .either => {
31786 // Prefer b, since it's a single peer
31787 reason.reset();
31788 reason.peers.set(b_peer_idx);
31789 },
31790 .both => {
31791 reason.peers.set(b_peer_idx);
31678 // Prefer the earliest peer
31679 reason_peer.* = @min(reason_peer.*, b_peer_idx);
3179231680 },
3179331681 }
3179431682
......@@ -31820,12 +31708,7 @@ const PeerResolveStrategy = enum {
3182031708const PeerResolveResult = union(enum) {
3182131709 /// The peer type resolution was successful, and resulted in the given type.
3182231710 success: Type,
31823 /// The chosen strategy was incompatible with the given peer.
31824 bad_strat: struct {
31825 strat: PeerResolveStrategy,
31826 peer_idx: usize,
31827 },
31828 /// There was some conflict between two specific peers.
31711 /// There was some generic conflict between two peers.
3182931712 conflict: struct {
3183031713 peer_idx_a: usize,
3183131714 peer_idx_b: usize,
......@@ -31847,7 +31730,6 @@ const PeerResolveResult = union(enum) {
3184731730 src: LazySrcLoc,
3184831731 instructions: []const Air.Inst.Ref,
3184931732 candidate_srcs: Module.PeerTypeCandidateSrc,
31850 strat_reason: PeerResolveStrategy.Reason,
3185131733 ) !*Module.ErrorMsg {
3185231734 const mod = sema.mod;
3185331735 const decl_ptr = mod.declPtr(block.src_decl);
......@@ -31867,41 +31749,6 @@ const PeerResolveResult = union(enum) {
3186731749
3186831750 switch (cur) {
3186931751 .success => unreachable,
31870 .bad_strat => |bad_strat| bad_strat: {
31871 if (strat_reason.peers.count() == 1) {
31872 // We can write this error more simply as a conflict between two peers
31873 conflict_idx = .{
31874 strat_reason.peers.findFirstSet().?,
31875 bad_strat.peer_idx,
31876 };
31877 break :bad_strat;
31878 }
31879
31880 const fmt = "type resolution strategy failed";
31881 const msg = if (opt_msg) |msg| msg: {
31882 try sema.errNote(block, src, msg, fmt, .{});
31883 break :msg msg;
31884 } else msg: {
31885 const msg = try sema.errMsg(block, src, fmt, .{});
31886 opt_msg = msg;
31887 break :msg msg;
31888 };
31889
31890 const peer_ty = peer_tys[bad_strat.peer_idx];
31891 const peer_src = candidate_srcs.resolve(mod, decl_ptr, bad_strat.peer_idx) orelse src;
31892 try sema.errNote(block, peer_src, msg, "strategy '{s}' failed for type '{}' here", .{ bad_strat.strat.name(), peer_ty.fmt(mod) });
31893
31894 try sema.errNote(block, src, msg, "strategy chosen using {} peers", .{strat_reason.peers.count()});
31895 var it = strat_reason.peers.iterator(.{});
31896 while (it.next()) |strat_peer_idx| {
31897 const strat_peer_ty = peer_tys[strat_peer_idx];
31898 const strat_peer_src = candidate_srcs.resolve(mod, decl_ptr, strat_peer_idx) orelse src;
31899 try sema.errNote(block, strat_peer_src, msg, "peer of type '{}' here", .{strat_peer_ty.fmt(mod)});
31900 }
31901
31902 // No child error
31903 break;
31904 },
3190531752 .conflict => |conflict| {
3190631753 // Fall through to two-peer conflict handling below
3190731754 conflict_idx = .{
......@@ -31925,7 +31772,7 @@ const PeerResolveResult = union(enum) {
3192531772 },
3192631773 }
3192731774
31928 // This is the path for reporting a conflict between two peers.
31775 // This is the path for reporting a generic conflict between two peers.
3192931776
3193031777 if (conflict_idx[1] < conflict_idx[0]) {
3193131778 // b comes first in source, so it's better if it comes first in the error
......@@ -31987,14 +31834,10 @@ fn resolvePeerTypes(
3198731834 val.* = try sema.resolveMaybeUndefVal(inst);
3198831835 }
3198931836
31990 var strat_reason: PeerResolveStrategy.Reason = .{
31991 .peers = try std.DynamicBitSet.initEmpty(sema.arena, instructions.len),
31992 };
31993
31994 switch (try sema.resolvePeerTypesInner(block, src, peer_tys, peer_vals, &strat_reason)) {
31837 switch (try sema.resolvePeerTypesInner(block, src, peer_tys, peer_vals)) {
3199531838 .success => |ty| return ty,
3199631839 else => |result| {
31997 const msg = try result.report(sema, block, src, instructions, candidate_srcs, strat_reason);
31840 const msg = try result.report(sema, block, src, instructions, candidate_srcs);
3199831841 return sema.failWithOwnedErrorMsg(msg);
3199931842 },
3200031843 }
......@@ -32006,16 +31849,14 @@ fn resolvePeerTypesInner(
3200631849 src: LazySrcLoc,
3200731850 peer_tys: []?Type,
3200831851 peer_vals: []?Value,
32009 strat_reason: *PeerResolveStrategy.Reason,
3201031852) !PeerResolveResult {
3201131853 const mod = sema.mod;
3201231854
32013 strat_reason.reset();
32014
31855 var strat_reason: usize = 0;
3201531856 var s: PeerResolveStrategy = .unknown;
3201631857 for (peer_tys, 0..) |opt_ty, i| {
3201731858 const ty = opt_ty orelse continue;
32018 s = s.merge(PeerResolveStrategy.select(ty, mod), strat_reason, i);
31859 s = s.merge(PeerResolveStrategy.select(ty, mod), &strat_reason, i);
3201931860 }
3202031861
3202131862 if (s == .unknown) {
......@@ -32041,9 +31882,9 @@ fn resolvePeerTypesInner(
3204131882 var final_set: ?Type = null;
3204231883 for (peer_tys, 0..) |opt_ty, i| {
3204331884 const ty = opt_ty orelse continue;
32044 if (ty.zigTypeTag(mod) != .ErrorSet) return .{ .bad_strat = .{
32045 .strat = s,
32046 .peer_idx = i,
31885 if (ty.zigTypeTag(mod) != .ErrorSet) return .{ .conflict = .{
31886 .peer_idx_a = strat_reason,
31887 .peer_idx_b = i,
3204731888 } };
3204831889 if (final_set) |cur_set| {
3204931890 final_set = try sema.maybeMergeErrorSets(block, src, cur_set, ty);
......@@ -32091,7 +31932,6 @@ fn resolvePeerTypesInner(
3209131932 src,
3209231933 peer_tys,
3209331934 peer_vals,
32094 strat_reason,
3209531935 )) {
3209631936 .success => |ty| ty,
3209731937 else => |result| return result,
......@@ -32102,9 +31942,9 @@ fn resolvePeerTypesInner(
3210231942 .nullable => {
3210331943 for (peer_tys, 0..) |opt_ty, i| {
3210431944 const ty = opt_ty orelse continue;
32105 if (!ty.eql(Type.null, mod)) return .{ .bad_strat = .{
32106 .strat = s,
32107 .peer_idx = i,
31945 if (!ty.eql(Type.null, mod)) return .{ .conflict = .{
31946 .peer_idx_a = strat_reason,
31947 .peer_idx_b = i,
3210831948 } };
3210931949 }
3211031950 return .{ .success = Type.null };
......@@ -32130,7 +31970,6 @@ fn resolvePeerTypesInner(
3213031970 src,
3213131971 peer_tys,
3213231972 peer_vals,
32133 strat_reason,
3213431973 )) {
3213531974 .success => |ty| ty,
3213631975 else => |result| return result,
......@@ -32154,9 +31993,9 @@ fn resolvePeerTypesInner(
3215431993
3215531994 if (!ty.isArrayOrVector(mod)) {
3215631995 // We allow tuples of the correct length. We won't validate their elem type, since the elements can be coerced.
32157 const arr_like = sema.typeIsArrayLike(ty) orelse return .{ .bad_strat = .{
32158 .strat = s,
32159 .peer_idx = i,
31996 const arr_like = sema.typeIsArrayLike(ty) orelse return .{ .conflict = .{
31997 .peer_idx_a = strat_reason,
31998 .peer_idx_b = i,
3216031999 } };
3216132000
3216232001 if (opt_first_idx) |first_idx| {
......@@ -32224,9 +32063,9 @@ fn resolvePeerTypesInner(
3222432063
3222532064 if (!ty.isArrayOrVector(mod)) {
3222632065 // Allow tuples of the correct length
32227 const arr_like = sema.typeIsArrayLike(ty) orelse return .{ .bad_strat = .{
32228 .strat = s,
32229 .peer_idx = i,
32066 const arr_like = sema.typeIsArrayLike(ty) orelse return .{ .conflict = .{
32067 .peer_idx_a = strat_reason,
32068 .peer_idx_b = i,
3223032069 } };
3223132070
3223232071 if (len) |expect_len| {
......@@ -32266,7 +32105,6 @@ fn resolvePeerTypesInner(
3226632105 src,
3226732106 peer_tys,
3226832107 peer_vals,
32269 strat_reason,
3227032108 )) {
3227132109 .success => |ty| ty,
3227232110 else => |result| return result,
......@@ -32300,9 +32138,9 @@ fn resolvePeerTypesInner(
3230032138 else => {},
3230132139 }
3230232140
32303 if (!ty.isPtrAtRuntime(mod)) return .{ .bad_strat = .{
32304 .strat = s,
32305 .peer_idx = i,
32141 if (!ty.isPtrAtRuntime(mod)) return .{ .conflict = .{
32142 .peer_idx_a = strat_reason,
32143 .peer_idx_b = i,
3230632144 } };
3230732145
3230832146 // Goes through optionals
......@@ -32316,7 +32154,6 @@ fn resolvePeerTypesInner(
3231632154 };
3231732155
3231832156 // Try peer -> cur, then cur -> peer
32319 const old_pointee_type = ptr_info.pointee_type;
3232032157 ptr_info.pointee_type = (try sema.resolvePairInMemoryCoercible(block, src, ptr_info.pointee_type, peer_info.pointee_type)) orelse {
3232132158 return .{ .conflict = .{
3232232159 .peer_idx_a = first_idx,
......@@ -32325,8 +32162,8 @@ fn resolvePeerTypesInner(
3232532162 };
3232632163
3232732164 if (ptr_info.sentinel != null and peer_info.sentinel != null) {
32328 const peer_sent = try sema.coerceValueInMemory(block, ptr_info.sentinel.?, old_pointee_type, ptr_info.pointee_type, .unneeded);
32329 const ptr_sent = try sema.coerceValueInMemory(block, peer_info.sentinel.?, peer_info.pointee_type, ptr_info.pointee_type, .unneeded);
32165 const peer_sent = try mod.getCoerced(ptr_info.sentinel.?, ptr_info.pointee_type);
32166 const ptr_sent = try mod.getCoerced(peer_info.sentinel.?, ptr_info.pointee_type);
3233032167 if (ptr_sent.eql(peer_sent, ptr_info.pointee_type, mod)) {
3233132168 ptr_info.sentinel = ptr_sent;
3233232169 } else {
......@@ -32379,18 +32216,18 @@ fn resolvePeerTypesInner(
3237932216 .pointee_type = ty,
3238032217 .@"addrspace" = target_util.defaultAddressSpace(target, .global_constant),
3238132218 },
32382 else => return .{ .bad_strat = .{
32383 .strat = s,
32384 .peer_idx = i,
32219 else => return .{ .conflict = .{
32220 .peer_idx_a = strat_reason,
32221 .peer_idx_b = i,
3238532222 } },
3238632223 };
3238732224
3238832225 switch (peer_info.size) {
3238932226 .One, .Many => {},
3239032227 .Slice => opt_slice_idx = i,
32391 .C => return .{ .bad_strat = .{
32392 .strat = s,
32393 .peer_idx = i,
32228 .C => return .{ .conflict = .{
32229 .peer_idx_a = strat_reason,
32230 .peer_idx_b = i,
3239432231 } },
3239532232 }
3239632233
......@@ -32605,10 +32442,8 @@ fn resolvePeerTypesInner(
3260532442 no_sentinel: {
3260632443 if (peer_sentinel == null) break :no_sentinel;
3260732444 if (cur_sentinel == null) break :no_sentinel;
32608 const peer_sent_ty = mod.intern_pool.typeOf(peer_sentinel.?.toIntern()).toType();
32609 const cur_sent_ty = mod.intern_pool.typeOf(cur_sentinel.?.toIntern()).toType();
32610 const peer_sent_coerced = try sema.coerceValueInMemory(block, peer_sentinel.?, peer_sent_ty, sentinel_ty, .unneeded);
32611 const cur_sent_coerced = try sema.coerceValueInMemory(block, cur_sentinel.?, cur_sent_ty, sentinel_ty, .unneeded);
32445 const peer_sent_coerced = try mod.getCoerced(peer_sentinel.?, sentinel_ty);
32446 const cur_sent_coerced = try mod.getCoerced(cur_sentinel.?, sentinel_ty);
3261232447 if (!peer_sent_coerced.eql(cur_sent_coerced, sentinel_ty, mod)) break :no_sentinel;
3261332448 // Sentinels match
3261432449 if (ptr_info.size == .One) {
......@@ -32664,9 +32499,9 @@ fn resolvePeerTypesInner(
3266432499 first_idx = i;
3266532500 continue;
3266632501 };
32667 if (ty.zigTypeTag(mod) != .Fn) return .{ .bad_strat = .{
32668 .strat = s,
32669 .peer_idx = i,
32502 if (ty.zigTypeTag(mod) != .Fn) return .{ .conflict = .{
32503 .peer_idx_a = strat_reason,
32504 .peer_idx_b = i,
3267032505 } };
3267132506 // ty -> cur_ty
3267232507 if (.ok == try sema.coerceInMemoryAllowedFns(block, cur_ty, ty, target, src, src)) {
......@@ -32694,9 +32529,9 @@ fn resolvePeerTypesInner(
3269432529 const ty = opt_ty orelse continue;
3269532530 switch (ty.zigTypeTag(mod)) {
3269632531 .EnumLiteral, .Enum, .Union => {},
32697 else => return .{ .bad_strat = .{
32698 .strat = s,
32699 .peer_idx = i,
32532 else => return .{ .conflict = .{
32533 .peer_idx_a = strat_reason,
32534 .peer_idx_b = i,
3270032535 } },
3270132536 }
3270232537 const cur_ty = opt_cur_ty orelse {
......@@ -32751,9 +32586,9 @@ fn resolvePeerTypesInner(
3275132586 const ty = opt_ty orelse continue;
3275232587 switch (ty.zigTypeTag(mod)) {
3275332588 .ComptimeInt => {},
32754 else => return .{ .bad_strat = .{
32755 .strat = s,
32756 .peer_idx = i,
32589 else => return .{ .conflict = .{
32590 .peer_idx_a = strat_reason,
32591 .peer_idx_b = i,
3275732592 } },
3275832593 }
3275932594 }
......@@ -32765,9 +32600,9 @@ fn resolvePeerTypesInner(
3276532600 const ty = opt_ty orelse continue;
3276632601 switch (ty.zigTypeTag(mod)) {
3276732602 .ComptimeInt, .ComptimeFloat => {},
32768 else => return .{ .bad_strat = .{
32769 .strat = s,
32770 .peer_idx = i,
32603 else => return .{ .conflict = .{
32604 .peer_idx_a = strat_reason,
32605 .peer_idx_b = i,
3277132606 } },
3277232607 }
3277332608 }
......@@ -32789,18 +32624,18 @@ fn resolvePeerTypesInner(
3278932624 switch (peer_tag) {
3279032625 .ComptimeInt => {
3279132626 // If the value is undefined, we can't refine to a fixed-width int
32792 if (opt_val == null or opt_val.?.isUndef(mod)) return .{ .bad_strat = .{
32793 .strat = s,
32794 .peer_idx = i,
32627 if (opt_val == null or opt_val.?.isUndef(mod)) return .{ .conflict = .{
32628 .peer_idx_a = strat_reason,
32629 .peer_idx_b = i,
3279532630 } };
3279632631 any_comptime_known = true;
3279732632 ptr_opt_val.* = try sema.resolveLazyValue(opt_val.?);
3279832633 continue;
3279932634 },
3280032635 .Int => {},
32801 else => return .{ .bad_strat = .{
32802 .strat = s,
32803 .peer_idx = i,
32636 else => return .{ .conflict = .{
32637 .peer_idx_a = strat_reason,
32638 .peer_idx_b = i,
3280432639 } },
3280532640 }
3280632641
......@@ -32868,9 +32703,9 @@ fn resolvePeerTypesInner(
3286832703 switch (ty.zigTypeTag(mod)) {
3286932704 .ComptimeFloat, .ComptimeInt => {},
3287032705 .Int => {
32871 if (opt_val == null) return .{ .bad_strat = .{
32872 .strat = s,
32873 .peer_idx = i,
32706 if (opt_val == null) return .{ .conflict = .{
32707 .peer_idx_a = strat_reason,
32708 .peer_idx_b = i,
3287432709 } };
3287532710 },
3287632711 .Float => {
......@@ -32890,9 +32725,9 @@ fn resolvePeerTypesInner(
3289032725 opt_cur_ty = ty;
3289132726 }
3289232727 },
32893 else => return .{ .bad_strat = .{
32894 .strat = s,
32895 .peer_idx = i,
32728 else => return .{ .conflict = .{
32729 .peer_idx_a = strat_reason,
32730 .peer_idx_b = i,
3289632731 } },
3289732732 }
3289832733 }
......@@ -32915,9 +32750,9 @@ fn resolvePeerTypesInner(
3291532750 const ty = opt_ty orelse continue;
3291632751
3291732752 if (!ty.isTupleOrAnonStruct(mod)) {
32918 return .{ .bad_strat = .{
32919 .strat = s,
32920 .peer_idx = i,
32753 return .{ .conflict = .{
32754 .peer_idx_a = strat_reason,
32755 .peer_idx_b = i,
3292132756 } };
3292232757 }
3292332758
......@@ -32973,7 +32808,7 @@ fn resolvePeerTypesInner(
3297332808 }
3297432809
3297532810 // Resolve field type recursively
32976 field_ty.* = switch (try sema.resolvePeerTypesInner(block, src, sub_peer_tys, sub_peer_vals, strat_reason)) {
32811 field_ty.* = switch (try sema.resolvePeerTypesInner(block, src, sub_peer_tys, sub_peer_vals)) {
3297732812 .success => |ty| ty.toIntern(),
3297832813 else => |result| {
3297932814 const result_buf = try sema.arena.create(PeerResolveResult);
......@@ -35538,7 +35373,7 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value
3553835373 // Move mutable decl values to the InternPool and assert other decls are already in
3553935374 // the InternPool.
3554035375 const uncoerced_val = if (deref.is_mutable) try tv.val.intern(tv.ty, mod) else tv.val.toIntern();
35541 const coerced_val = try sema.coerceValueInMemory(block, uncoerced_val.toValue(), tv.ty, load_ty, src);
35376 const coerced_val = try mod.getCoerced(uncoerced_val.toValue(), load_ty);
3554235377 return .{ .val = coerced_val };
3554335378 }
3554435379 }