authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-09-24 14:31:00-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-09-25 03:02:05-07:00
logefc98fcbebfd91b65b3de6070718247aafcc1c33
treecfbb1ada9f556e2c7ecab7cae45b7e371b71993f
parenta40cdad18c06fd377622c47aa34564df7ea959b5

disallow non-scalar sentinel types

see #17969

4 files changed, 26 insertions(+), 34 deletions(-)

lib/std/builtin.zig-6
......@@ -887,12 +887,6 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr
887887 }
888888}
889889
890pub fn checkNonScalarSentinel(expected: anytype, actual: @TypeOf(expected)) void {
891 if (!std.meta.eql(expected, actual)) {
892 panicSentinelMismatch(expected, actual);
893 }
894}
895
896890pub fn panicSentinelMismatch(expected: anytype, actual: @TypeOf(expected)) noreturn {
897891 @branchHint(.cold);
898892 std.debug.panicExtra(null, @returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{ expected, actual });
src/Sema.zig+13-7
......@@ -19741,6 +19741,14 @@ fn checkNullableType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !voi
1974119741 return sema.failWithExpectedOptionalType(block, src, ty);
1974219742}
1974319743
19744fn checkSentinelType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
19745 const pt = sema.pt;
19746 const zcu = pt.zcu;
19747 if (!ty.isSelfComparable(zcu, true)) {
19748 return sema.fail(block, src, "non-scalar sentinel type '{}'", .{ty.fmt(pt)});
19749 }
19750}
19751
1974419752fn zirIsNonNull(
1974519753 sema: *Sema,
1974619754 block: *Block,
......@@ -20542,6 +20550,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2054220550 const val = try sema.resolveConstDefinedValue(block, sentinel_src, coerced, .{
2054320551 .needed_comptime_reason = "pointer sentinel value must be comptime-known",
2054420552 });
20553 try checkSentinelType(sema, block, sentinel_src, elem_ty);
2054520554 break :blk val.toIntern();
2054620555 } else .none;
2054720556
......@@ -28114,13 +28123,9 @@ fn panicSentinelMismatch(
2811428123 .operation = .And,
2811528124 } },
2811628125 });
28117 } else if (sentinel_ty.isSelfComparable(zcu, true))
28118 try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel)
28119 else {
28120 const panic_fn = try pt.getBuiltin("checkNonScalarSentinel");
28121 const args: [2]Air.Inst.Ref = .{ expected_sentinel, actual_sentinel };
28122 try sema.callBuiltin(parent_block, src, panic_fn, .auto, &args, .@"safety check");
28123 return;
28126 } else ok: {
28127 assert(sentinel_ty.isSelfComparable(zcu, true));
28128 break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel);
2812428129 };
2812528130
2812628131 if (!pt.zcu.comp.formatted_panics) {
......@@ -33573,6 +33578,7 @@ fn analyzeSlice(
3357333578 const sentinel = s: {
3357433579 if (sentinel_opt != .none) {
3357533580 const casted = try sema.coerce(block, elem_ty, sentinel_opt, sentinel_src);
33581 try checkSentinelType(sema, block, sentinel_src, elem_ty);
3357633582 break :s try sema.resolveConstDefinedValue(block, sentinel_src, casted, .{
3357733583 .needed_comptime_reason = "slice sentinel must be comptime-known",
3357833584 });
test/cases/compile_errors/array slice sentinel mismatch non-scalar.zig created+13
......@@ -0,0 +1,13 @@
1export fn foo() void {
2 const S = struct { a: u32 };
3 var arr = [_]S{ .{ .a = 1 }, .{ .a = 2 } };
4 const s = arr[0..1 :.{ .a = 1 }];
5 _ = s;
6}
7
8// error
9// backend=stage2
10// target=native
11//
12// :4:26: error: non-scalar sentinel type 'tmp.foo.S'
13// :2:15: note: struct declared here
test/cases/safety/array slice sentinel mismatch non-scalar.zig deleted-21
......@@ -1,21 +0,0 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "sentinel mismatch: expected tmp.main.S{ .a = 1 }, found tmp.main.S{ .a = 2 }")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10
11pub fn main() !void {
12 const S = struct { a: u32 };
13 var arr = [_]S{ .{ .a = 1 }, .{ .a = 2 } };
14 const s = arr[0..1 :.{ .a = 1 }];
15 _ = s;
16 return error.TestFailed;
17}
18
19// run
20// backend=llvm
21// target=native