Commit a9d544575d
Changed files (4)
src
test
cases
compile_errors
src/Sema/comptime_ptr_access.zig
@@ -321,6 +321,7 @@ fn loadComptimePtrInner(
zcu.getTarget(),
src,
src,
+ null,
)) {
// We already have a value which is IMC to the desired type.
return .{ .success = base_val };
@@ -353,6 +354,7 @@ fn loadComptimePtrInner(
zcu.getTarget(),
src,
src,
+ null,
)) {
// Changing the length of an array.
const skip_base: u64 = extra_base_index + if (load_ty.zigTypeTag(zcu) == .Array) skip: {
@@ -721,6 +723,7 @@ fn prepareComptimePtrStore(
zcu.getTarget(),
src,
src,
+ null,
)) {
// The base strategy already gets us a value which the desired type is IMC to.
return base_strat;
@@ -753,7 +756,7 @@ fn prepareComptimePtrStore(
else => unreachable,
};
const val_one_ty, const val_count = base_val.typeOf(zcu).arrayBase(zcu);
- if (.ok != try sema.coerceInMemoryAllowed(block, val_one_ty, store_one_ty, true, zcu.getTarget(), src, src)) {
+ if (.ok != try sema.coerceInMemoryAllowed(block, val_one_ty, store_one_ty, true, zcu.getTarget(), src, src, null)) {
break :restructure_array;
}
if (base_elem_offset + extra_base_index + store_count > val_count) return .{ .out_of_bounds = oob_ty };
src/Sema.zig
@@ -11312,7 +11312,7 @@ const SwitchProngAnalysis = struct {
const first_non_imc = in_mem: {
for (field_indices, 0..) |field_idx, i| {
const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_idx]);
- if (.ok != try sema.coerceInMemoryAllowed(block, capture_ty, field_ty, false, zcu.getTarget(), LazySrcLoc.unneeded, LazySrcLoc.unneeded)) {
+ if (.ok != try sema.coerceInMemoryAllowed(block, capture_ty, field_ty, false, zcu.getTarget(), LazySrcLoc.unneeded, LazySrcLoc.unneeded, null)) {
break :in_mem i;
}
}
@@ -11335,7 +11335,7 @@ const SwitchProngAnalysis = struct {
const next = first_non_imc + 1;
for (field_indices[next..], next..) |field_idx, i| {
const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_idx]);
- if (.ok != try sema.coerceInMemoryAllowed(block, capture_ty, field_ty, false, zcu.getTarget(), LazySrcLoc.unneeded, LazySrcLoc.unneeded)) {
+ if (.ok != try sema.coerceInMemoryAllowed(block, capture_ty, field_ty, false, zcu.getTarget(), LazySrcLoc.unneeded, LazySrcLoc.unneeded, null)) {
in_mem_coercible.unset(i);
}
}
@@ -23162,6 +23162,7 @@ fn ptrCastFull(
mod.getTarget(),
src,
operand_src,
+ null,
);
if (imc_res == .ok) break :check_child;
return sema.failWithOwnedErrorMsg(block, msg: {
@@ -25772,7 +25773,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
const dest_elem_ty = dest_ty.elemType2(mod);
const src_elem_ty = src_ty.elemType2(mod);
- if (.ok != try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, true, target, dest_src, src_src)) {
+ if (.ok != try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, true, target, dest_src, src_src, null)) {
return sema.fail(block, src, "TODO: lower @memcpy to a for loop because the element types have different ABI sizes", .{});
}
@@ -29188,7 +29189,7 @@ fn coerceExtra(
const maybe_inst_val = try sema.resolveValue(inst);
- var in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src);
+ var in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src, maybe_inst_val);
if (in_memory_result == .ok) {
if (maybe_inst_val) |val| {
return sema.coerceInMemory(val, dest_ty);
@@ -29243,7 +29244,7 @@ fn coerceExtra(
error.NotCoercible => {
if (in_memory_result == .no_match) {
// Try to give more useful notes
- in_memory_result = try sema.coerceInMemoryAllowed(block, child_type, inst_ty, false, target, dest_ty_src, inst_src);
+ in_memory_result = try sema.coerceInMemoryAllowed(block, child_type, inst_ty, false, target, dest_ty_src, inst_src, maybe_inst_val);
}
break :optional;
},
@@ -29273,7 +29274,7 @@ fn coerceExtra(
const array_elem_ty = array_ty.childType(zcu);
if (array_ty.arrayLen(zcu) != 1) break :single_item;
const dest_is_mut = !dest_info.flags.is_const;
- switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) {
+ switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, maybe_inst_val)) {
.ok => {},
else => break :single_item,
}
@@ -29290,7 +29291,7 @@ fn coerceExtra(
const dest_is_mut = !dest_info.flags.is_const;
const dst_elem_type = Type.fromInterned(dest_info.child);
- const elem_res = try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src);
+ const elem_res = try sema.coerceInMemoryAllowed(block, dst_elem_type, array_elem_type, dest_is_mut, target, dest_ty_src, inst_src, maybe_inst_val);
switch (elem_res) {
.ok => {},
else => {
@@ -29351,7 +29352,7 @@ fn coerceExtra(
const src_elem_ty = inst_ty.childType(zcu);
const dest_is_mut = !dest_info.flags.is_const;
const dst_elem_type = Type.fromInterned(dest_info.child);
- switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, src_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) {
+ switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, src_elem_ty, dest_is_mut, target, dest_ty_src, inst_src, maybe_inst_val)) {
.ok => {},
else => break :src_c_ptr,
}
@@ -29404,7 +29405,7 @@ fn coerceExtra(
const addr = sema.coerceExtra(block, ptr_size_ty, inst, inst_src, .{ .report_err = false }) catch |err| switch (err) {
error.NotCoercible => {
// Try to give more useful notes
- in_memory_result = try sema.coerceInMemoryAllowed(block, ptr_size_ty, inst_ty, false, target, dest_ty_src, inst_src);
+ in_memory_result = try sema.coerceInMemoryAllowed(block, ptr_size_ty, inst_ty, false, target, dest_ty_src, inst_src, maybe_inst_val);
break :pointer;
},
else => |e| return e,
@@ -29422,6 +29423,7 @@ fn coerceExtra(
target,
dest_ty_src,
inst_src,
+ maybe_inst_val,
)) {
.ok => {},
else => break :p,
@@ -29526,6 +29528,7 @@ fn coerceExtra(
target,
dest_ty_src,
inst_src,
+ maybe_inst_val,
)) {
.ok => {},
else => break :p,
@@ -29705,7 +29708,14 @@ fn coerceExtra(
else => eu: {
// T to E!T
return sema.wrapErrorUnionPayload(block, dest_ty, inst, inst_src) catch |err| switch (err) {
- error.NotCoercible => break :eu,
+ error.NotCoercible => {
+ if (in_memory_result == .no_match) {
+ const payload_type = dest_ty.errorUnionPayload(zcu);
+ // Try to give more useful notes
+ in_memory_result = try sema.coerceInMemoryAllowed(block, payload_type, inst_ty, false, target, dest_ty_src, inst_src, maybe_inst_val);
+ }
+ break :eu;
+ },
else => |e| return e,
};
},
@@ -29730,6 +29740,7 @@ fn coerceExtra(
target,
dest_ty_src,
inst_src,
+ maybe_inst_val,
)) {
break :array_to_array;
}
@@ -29805,7 +29816,7 @@ fn coerceExtra(
// E!T to T
if (inst_ty.zigTypeTag(zcu) == .ErrorUnion and
- (try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(zcu), dest_ty, false, target, dest_ty_src, inst_src)) == .ok)
+ (try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(zcu), dest_ty, false, target, dest_ty_src, inst_src, maybe_inst_val)) == .ok)
{
try sema.errNote(inst_src, msg, "cannot convert error union to payload type", .{});
try sema.errNote(inst_src, msg, "consider using 'try', 'catch', or 'if'", .{});
@@ -29813,7 +29824,7 @@ fn coerceExtra(
// ?T to T
if (inst_ty.zigTypeTag(zcu) == .Optional and
- (try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(zcu), dest_ty, false, target, dest_ty_src, inst_src)) == .ok)
+ (try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(zcu), dest_ty, false, target, dest_ty_src, inst_src, maybe_inst_val)) == .ok)
{
try sema.errNote(inst_src, msg, "cannot convert optional to payload type", .{});
try sema.errNote(inst_src, msg, "consider using '.?', 'orelse', or 'if'", .{});
@@ -29859,6 +29870,7 @@ const InMemoryCoercionResult = union(enum) {
ok,
no_match: Pair,
int_not_coercible: Int,
+ comptime_int_not_coercible: TypeValuePair,
error_union_payload: PairAndChild,
array_len: IntPair,
array_sentinel: Sentinel,
@@ -29895,6 +29907,11 @@ const InMemoryCoercionResult = union(enum) {
wanted: Type,
};
+ const TypeValuePair = struct {
+ actual: Value,
+ wanted: Type,
+ };
+
const PairAndChild = struct {
child: *InMemoryCoercionResult,
actual: Type,
@@ -29988,6 +30005,12 @@ const InMemoryCoercionResult = union(enum) {
});
break;
},
+ .comptime_int_not_coercible => |int| {
+ try sema.errNote(src, msg, "type '{}' cannot represent value '{}'", .{
+ int.wanted.fmt(pt), int.actual.fmtValue(pt, sema),
+ });
+ break;
+ },
.error_union_payload => |pair| {
try sema.errNote(src, msg, "error union payload '{}' cannot cast into error union payload '{}'", .{
pair.actual.fmt(pt), pair.wanted.fmt(pt),
@@ -30229,6 +30252,7 @@ pub fn coerceInMemoryAllowed(
target: std.Target,
dest_src: LazySrcLoc,
src_src: LazySrcLoc,
+ src_val: ?Value,
) CompileError!InMemoryCoercionResult {
const pt = sema.pt;
const mod = pt.zcu;
@@ -30264,6 +30288,15 @@ pub fn coerceInMemoryAllowed(
}
}
+ // Comptime int to regular int.
+ if (dest_tag == .Int and src_tag == .ComptimeInt) {
+ if (src_val) |val| {
+ if (!(try sema.intFitsInType(val, dest_ty, null))) {
+ return .{ .comptime_int_not_coercible = .{ .wanted = dest_ty, .actual = val } };
+ }
+ }
+ }
+
// Differently-named floats with the same number of bits.
if (dest_tag == .Float and src_tag == .Float) {
const dest_bits = dest_ty.floatBits(target);
@@ -30296,7 +30329,7 @@ pub fn coerceInMemoryAllowed(
if (dest_tag == .ErrorUnion and src_tag == .ErrorUnion) {
const dest_payload = dest_ty.errorUnionPayload(mod);
const src_payload = src_ty.errorUnionPayload(mod);
- const child = try sema.coerceInMemoryAllowed(block, dest_payload, src_payload, dest_is_mut, target, dest_src, src_src);
+ const child = try sema.coerceInMemoryAllowed(block, dest_payload, src_payload, dest_is_mut, target, dest_src, src_src, null);
if (child != .ok) {
return InMemoryCoercionResult{ .error_union_payload = .{
.child = try child.dupe(sema.arena),
@@ -30304,7 +30337,7 @@ pub fn coerceInMemoryAllowed(
.wanted = dest_payload,
} };
}
- return try sema.coerceInMemoryAllowed(block, dest_ty.errorUnionSet(mod), src_ty.errorUnionSet(mod), dest_is_mut, target, dest_src, src_src);
+ return try sema.coerceInMemoryAllowed(block, dest_ty.errorUnionSet(mod), src_ty.errorUnionSet(mod), dest_is_mut, target, dest_src, src_src, null);
}
// Error Sets
@@ -30323,7 +30356,7 @@ pub fn coerceInMemoryAllowed(
} };
}
- const child = try sema.coerceInMemoryAllowed(block, dest_info.elem_type, src_info.elem_type, dest_is_mut, target, dest_src, src_src);
+ const child = try sema.coerceInMemoryAllowed(block, dest_info.elem_type, src_info.elem_type, dest_is_mut, target, dest_src, src_src, null);
if (child != .ok) {
return InMemoryCoercionResult{ .array_elem = .{
.child = try child.dupe(sema.arena),
@@ -30362,7 +30395,7 @@ pub fn coerceInMemoryAllowed(
const dest_elem_ty = dest_ty.scalarType(mod);
const src_elem_ty = src_ty.scalarType(mod);
- const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src);
+ const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src, null);
if (child != .ok) {
return InMemoryCoercionResult{ .vector_elem = .{
.child = try child.dupe(sema.arena),
@@ -30389,7 +30422,7 @@ pub fn coerceInMemoryAllowed(
const dest_elem_ty = dest_ty.childType(mod);
const src_elem_ty = src_ty.childType(mod);
- const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src);
+ const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src, null);
if (child != .ok) {
return InMemoryCoercionResult{ .array_elem = .{
.child = try child.dupe(sema.arena),
@@ -30429,7 +30462,7 @@ pub fn coerceInMemoryAllowed(
const dest_child_type = dest_ty.optionalChild(mod);
const src_child_type = src_ty.optionalChild(mod);
- const child = try sema.coerceInMemoryAllowed(block, dest_child_type, src_child_type, dest_is_mut, target, dest_src, src_src);
+ const child = try sema.coerceInMemoryAllowed(block, dest_child_type, src_child_type, dest_is_mut, target, dest_src, src_src, null);
if (child != .ok) {
return InMemoryCoercionResult{ .optional_child = .{
.child = try child.dupe(sema.arena),
@@ -30451,7 +30484,7 @@ pub fn coerceInMemoryAllowed(
if (dest_ty.structFieldAlign(field_idx, pt) != src_ty.structFieldAlign(field_idx, pt)) break :tuple;
const dest_field_ty = dest_ty.structFieldType(field_idx, mod);
const src_field_ty = src_ty.structFieldType(field_idx, mod);
- const field = try sema.coerceInMemoryAllowed(block, dest_field_ty, src_field_ty, dest_is_mut, target, dest_src, src_src);
+ const field = try sema.coerceInMemoryAllowed(block, dest_field_ty, src_field_ty, dest_is_mut, target, dest_src, src_src, null);
if (field != .ok) break :tuple;
}
return .ok;
@@ -30598,7 +30631,7 @@ fn coerceInMemoryAllowedFns(
else => {
const dest_return_type = Type.fromInterned(dest_info.return_type);
const src_return_type = Type.fromInterned(src_info.return_type);
- const rt = try sema.coerceInMemoryAllowed(block, dest_return_type, src_return_type, false, target, dest_src, src_src);
+ const rt = try sema.coerceInMemoryAllowed(block, dest_return_type, src_return_type, false, target, dest_src, src_src, null);
if (rt != .ok) {
return InMemoryCoercionResult{ .fn_return_type = .{
.child = try rt.dupe(sema.arena),
@@ -30644,7 +30677,7 @@ fn coerceInMemoryAllowedFns(
.generic_poison_type => {},
else => {
// Note: Cast direction is reversed here.
- const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, false, target, dest_src, src_src);
+ const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, false, target, dest_src, src_src, null);
if (param != .ok) {
return InMemoryCoercionResult{ .fn_param = .{
.child = try param.dupe(sema.arena),
@@ -30708,13 +30741,13 @@ fn coerceInMemoryAllowedPtrs(
const dest_child = Type.fromInterned(dest_info.child);
const src_child = Type.fromInterned(src_info.child);
- const child = try sema.coerceInMemoryAllowed(block, dest_child, src_child, !dest_info.flags.is_const, target, dest_src, src_src);
+ const child = try sema.coerceInMemoryAllowed(block, dest_child, src_child, !dest_info.flags.is_const, target, dest_src, src_src, null);
if (child != .ok) allow: {
// As a special case, we also allow coercing `*[n:s]T` to `*[n]T`, akin to dropping the sentinel from a slice.
// `*[n:s]T` cannot coerce in memory to `*[n]T` since they have different sizes.
if (src_child.zigTypeTag(zcu) == .Array and dest_child.zigTypeTag(zcu) == .Array and
src_child.sentinel(zcu) != null and dest_child.sentinel(zcu) == null and
- .ok == try sema.coerceInMemoryAllowed(block, dest_child.childType(zcu), src_child.childType(zcu), !dest_info.flags.is_const, target, dest_src, src_src))
+ .ok == try sema.coerceInMemoryAllowed(block, dest_child.childType(zcu), src_child.childType(zcu), !dest_info.flags.is_const, target, dest_src, src_src, null))
{
break :allow;
}
@@ -31593,7 +31626,7 @@ fn coerceArrayLike(
const target = mod.getTarget();
// try coercion of the whole array
- const in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src);
+ const in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src, null);
if (in_memory_result == .ok) {
if (try sema.resolveValue(inst)) |inst_val| {
// These types share the same comptime value representation.
@@ -34108,13 +34141,13 @@ fn resolvePeerTypesInner(
const peer_elem_ty = ty.childType(mod);
if (!peer_elem_ty.eql(elem_ty, mod)) coerce: {
const peer_elem_coerces_to_elem =
- try sema.coerceInMemoryAllowed(block, elem_ty, peer_elem_ty, false, mod.getTarget(), src, src);
+ try sema.coerceInMemoryAllowed(block, elem_ty, peer_elem_ty, false, mod.getTarget(), src, src, null);
if (peer_elem_coerces_to_elem == .ok) {
break :coerce;
}
const elem_coerces_to_peer_elem =
- try sema.coerceInMemoryAllowed(block, peer_elem_ty, elem_ty, false, mod.getTarget(), src, src);
+ try sema.coerceInMemoryAllowed(block, peer_elem_ty, elem_ty, false, mod.getTarget(), src, src, null);
if (elem_coerces_to_peer_elem == .ok) {
elem_ty = peer_elem_ty;
break :coerce;
@@ -35039,12 +35072,12 @@ fn resolvePairInMemoryCoercible(sema: *Sema, block: *Block, src: LazySrcLoc, ty_
const target = sema.pt.zcu.getTarget();
// ty_b -> ty_a
- if (.ok == try sema.coerceInMemoryAllowed(block, ty_a, ty_b, true, target, src, src)) {
+ if (.ok == try sema.coerceInMemoryAllowed(block, ty_a, ty_b, true, target, src, src, null)) {
return ty_a;
}
// ty_a -> ty_b
- if (.ok == try sema.coerceInMemoryAllowed(block, ty_b, ty_a, true, target, src, src)) {
+ if (.ok == try sema.coerceInMemoryAllowed(block, ty_b, ty_a, true, target, src, src, null)) {
return ty_b;
}
test/cases/compile_errors/coercion_to_error_union.zig
@@ -0,0 +1,11 @@
+export fn b() void {
+ const x: anyerror!u8 = 256;
+ _ = x;
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// 2:28: error: expected type 'anyerror!u8', found 'comptime_int'
+// 2:28: note: type 'u8' cannot represent value '256'
test/cases/compile_errors/coercion_to_optional.zig
@@ -0,0 +1,11 @@
+export fn a() void {
+ const x: ?u8 = 256;
+ _ = x;
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// 2:20: error: expected type '?u8', found 'comptime_int'
+// 2:20: note: type 'u8' cannot represent value '256'