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...@@ -887,12 +887,6 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr
887 }887 }
888}888}
889889
890pub fn checkNonScalarSentinel(expected: anytype, actual: @TypeOf(expected)) void {
891 if (!std.meta.eql(expected, actual)) {
892 panicSentinelMismatch(expected, actual);
893 }
894}
895
896pub fn panicSentinelMismatch(expected: anytype, actual: @TypeOf(expected)) noreturn {890pub fn panicSentinelMismatch(expected: anytype, actual: @TypeOf(expected)) noreturn {
897 @branchHint(.cold);891 @branchHint(.cold);
898 std.debug.panicExtra(null, @returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{ expected, actual });892 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...@@ -19741,6 +19741,14 @@ fn checkNullableType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !voi
19741 return sema.failWithExpectedOptionalType(block, src, ty);19741 return sema.failWithExpectedOptionalType(block, src, ty);
19742}19742}
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
19744fn zirIsNonNull(19752fn zirIsNonNull(
19745 sema: *Sema,19753 sema: *Sema,
19746 block: *Block,19754 block: *Block,
...@@ -20542,6 +20550,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20542,6 +20550,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20542 const val = try sema.resolveConstDefinedValue(block, sentinel_src, coerced, .{20550 const val = try sema.resolveConstDefinedValue(block, sentinel_src, coerced, .{
20543 .needed_comptime_reason = "pointer sentinel value must be comptime-known",20551 .needed_comptime_reason = "pointer sentinel value must be comptime-known",
20544 });20552 });
20553 try checkSentinelType(sema, block, sentinel_src, elem_ty);
20545 break :blk val.toIntern();20554 break :blk val.toIntern();
20546 } else .none;20555 } else .none;
2054720556
...@@ -28114,13 +28123,9 @@ fn panicSentinelMismatch(...@@ -28114,13 +28123,9 @@ fn panicSentinelMismatch(
28114 .operation = .And,28123 .operation = .And,
28115 } },28124 } },
28116 });28125 });
28117 } else if (sentinel_ty.isSelfComparable(zcu, true))28126 } else ok: {
28118 try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel)28127 assert(sentinel_ty.isSelfComparable(zcu, true));
28119 else {28128 break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel);
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;
28124 };28129 };
2812528130
28126 if (!pt.zcu.comp.formatted_panics) {28131 if (!pt.zcu.comp.formatted_panics) {
...@@ -33573,6 +33578,7 @@ fn analyzeSlice(...@@ -33573,6 +33578,7 @@ fn analyzeSlice(
33573 const sentinel = s: {33578 const sentinel = s: {
33574 if (sentinel_opt != .none) {33579 if (sentinel_opt != .none) {
33575 const casted = try sema.coerce(block, elem_ty, sentinel_opt, sentinel_src);33580 const casted = try sema.coerce(block, elem_ty, sentinel_opt, sentinel_src);
33581 try checkSentinelType(sema, block, sentinel_src, elem_ty);
33576 break :s try sema.resolveConstDefinedValue(block, sentinel_src, casted, .{33582 break :s try sema.resolveConstDefinedValue(block, sentinel_src, casted, .{
33577 .needed_comptime_reason = "slice sentinel must be comptime-known",33583 .needed_comptime_reason = "slice sentinel must be comptime-known",
33578 });33584 });
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