diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index ccd46d874d..abbdf89c0a 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -887,12 +887,6 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr } } -pub fn checkNonScalarSentinel(expected: anytype, actual: @TypeOf(expected)) void { - if (!std.meta.eql(expected, actual)) { - panicSentinelMismatch(expected, actual); - } -} - pub fn panicSentinelMismatch(expected: anytype, actual: @TypeOf(expected)) noreturn { @branchHint(.cold); std.debug.panicExtra(null, @returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{ expected, actual }); diff --git a/src/Sema.zig b/src/Sema.zig index 40556d2136..406dbebc31 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -19741,6 +19741,14 @@ fn checkNullableType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !voi return sema.failWithExpectedOptionalType(block, src, ty); } +fn checkSentinelType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void { + const pt = sema.pt; + const zcu = pt.zcu; + if (!ty.isSelfComparable(zcu, true)) { + return sema.fail(block, src, "non-scalar sentinel type '{}'", .{ty.fmt(pt)}); + } +} + fn zirIsNonNull( sema: *Sema, block: *Block, @@ -20542,6 +20550,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const val = try sema.resolveConstDefinedValue(block, sentinel_src, coerced, .{ .needed_comptime_reason = "pointer sentinel value must be comptime-known", }); + try checkSentinelType(sema, block, sentinel_src, elem_ty); break :blk val.toIntern(); } else .none; @@ -28114,13 +28123,9 @@ fn panicSentinelMismatch( .operation = .And, } }, }); - } else if (sentinel_ty.isSelfComparable(zcu, true)) - try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel) - else { - const panic_fn = try pt.getBuiltin("checkNonScalarSentinel"); - const args: [2]Air.Inst.Ref = .{ expected_sentinel, actual_sentinel }; - try sema.callBuiltin(parent_block, src, panic_fn, .auto, &args, .@"safety check"); - return; + } else ok: { + assert(sentinel_ty.isSelfComparable(zcu, true)); + break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel); }; if (!pt.zcu.comp.formatted_panics) { @@ -33573,6 +33578,7 @@ fn analyzeSlice( const sentinel = s: { if (sentinel_opt != .none) { const casted = try sema.coerce(block, elem_ty, sentinel_opt, sentinel_src); + try checkSentinelType(sema, block, sentinel_src, elem_ty); break :s try sema.resolveConstDefinedValue(block, sentinel_src, casted, .{ .needed_comptime_reason = "slice sentinel must be comptime-known", }); diff --git a/test/cases/compile_errors/array slice sentinel mismatch non-scalar.zig b/test/cases/compile_errors/array slice sentinel mismatch non-scalar.zig new file mode 100644 index 0000000000..085caffc99 --- /dev/null +++ b/test/cases/compile_errors/array slice sentinel mismatch non-scalar.zig @@ -0,0 +1,13 @@ +export fn foo() void { + const S = struct { a: u32 }; + var arr = [_]S{ .{ .a = 1 }, .{ .a = 2 } }; + const s = arr[0..1 :.{ .a = 1 }]; + _ = s; +} + +// error +// backend=stage2 +// target=native +// +// :4:26: error: non-scalar sentinel type 'tmp.foo.S' +// :2:15: note: struct declared here diff --git a/test/cases/safety/array slice sentinel mismatch non-scalar.zig b/test/cases/safety/array slice sentinel mismatch non-scalar.zig deleted file mode 100644 index 5523970168..0000000000 --- a/test/cases/safety/array slice sentinel mismatch non-scalar.zig +++ /dev/null @@ -1,21 +0,0 @@ -const std = @import("std"); - -pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { - _ = stack_trace; - if (std.mem.eql(u8, message, "sentinel mismatch: expected tmp.main.S{ .a = 1 }, found tmp.main.S{ .a = 2 }")) { - std.process.exit(0); - } - std.process.exit(1); -} - -pub fn main() !void { - const S = struct { a: u32 }; - var arr = [_]S{ .{ .a = 1 }, .{ .a = 2 } }; - const s = arr[0..1 :.{ .a = 1 }]; - _ = s; - return error.TestFailed; -} - -// run -// backend=llvm -// target=native