authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-01-24 02:19:28+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-01-24 19:29:51+00:00
log83991efe10d92c4b920d7b7fc75be98ed7854ad7
tree7137ee5eb01517aede1c5503c29a2003fca71f80
parentb3d9b0e3f6bab5d662ec385cf754872f8a90607f
signaturelock-open Commit is signed but in an unrecognized format.

compiler: yet more panic handler changes

* `std.builtin.Panic` -> `std.builtin.panic`, because it is a namespace. * `root.Panic` -> `root.panic` for the same reason. There are type checks so that we still allow the legacy `pub fn panic` strategy in the 0.14.0 release. * `std.debug.SimplePanic` -> `std.debug.simple_panic`, same reason. * `std.debug.NoPanic` -> `std.debug.no_panic`, same reason. * `std.debug.FormattedPanic` is now a function `std.debug.FullPanic` which takes as input a `panicFn` and returns a namespace with all the panic functions. This handles the incredibly common case of just wanting to override how the message is printed, whilst keeping nice formatted panics. * Remove `std.builtin.panic.messages`; now, every safety panic has its own function. This reduces binary bloat, as calls to these functions no longer need to prepare any arguments (aside from the error return trace). * Remove some legacy declarations, since a zig1.wasm update has happened. Most of these were related to the panic handler, but a quick grep for "zig1" brought up a couple more results too. Also, add some missing type checks to Sema. Resolves: #22584 formatted -> full

20 files changed, 864 insertions(+), 482 deletions(-)

lib/std/Target.zig+1-1
......@@ -370,7 +370,7 @@ pub const Os = struct {
370370 range: std.SemanticVersion.Range,
371371 glibc: std.SemanticVersion,
372372 /// Android API level.
373 android: u32 = 14, // This default value is to be deleted after zig1.wasm is updated.
373 android: u32,
374374
375375 pub inline fn includesVersion(range: LinuxVersionRange, ver: std.SemanticVersion) bool {
376376 return range.range.includesVersion(ver);
lib/std/builtin.zig+16-33
......@@ -1110,45 +1110,28 @@ pub const TestFn = struct {
11101110/// Deprecated, use the `Panic` namespace instead.
11111111/// To be deleted after 0.14.0 is released.
11121112pub const PanicFn = fn ([]const u8, ?*StackTrace, ?usize) noreturn;
1113/// Deprecated, use the `Panic` namespace instead.
1114/// To be deleted after 0.14.0 is released.
1115pub const panic: PanicFn = Panic.call;
11161113
11171114/// This namespace is used by the Zig compiler to emit various kinds of safety
1118/// panics. These can be overridden by making a public `Panic` namespace in the
1115/// panics. These can be overridden by making a public `panic` namespace in the
11191116/// root source file.
1120pub const Panic: type = if (@hasDecl(root, "Panic"))
1121 root.Panic
1122else if (@hasDecl(root, "panic")) // Deprecated, use `Panic` instead.
1123 DeprecatedPanic
1124else if (builtin.zig_backend == .stage2_riscv64)
1125 std.debug.SimplePanic // https://github.com/ziglang/zig/issues/21519
1126else
1127 std.debug.FormattedPanic;
1128
1129/// To be deleted after 0.14.0 is released.
1130const DeprecatedPanic = struct {
1131 pub const call = root.panic;
1132 pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
1133 pub const unwrapError = std.debug.FormattedPanic.unwrapError;
1134 pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
1135 pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
1136 pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
1137 pub const messages = std.debug.FormattedPanic.messages;
1117pub const panic: type = p: {
1118 if (@hasDecl(root, "panic")) {
1119 if (@TypeOf(root.panic) != type) {
1120 break :p std.debug.FullPanic(root.panic); // Deprecated; make `panic` a namespace instead.
1121 }
1122 break :p root.panic;
1123 }
1124 if (@hasDecl(root, "Panic")) {
1125 break :p root.Panic; // Deprecated; use `panic` instead.
1126 }
1127 if (builtin.zig_backend == .stage2_riscv64) {
1128 break :p std.debug.simple_panic;
1129 }
1130 break :p std.debug.FullPanic(std.debug.defaultPanic);
11381131};
11391132
11401133/// To be deleted after zig1.wasm is updated.
1141pub const panicSentinelMismatch = Panic.sentinelMismatch;
1142/// To be deleted after zig1.wasm is updated.
1143pub const panicUnwrapError = Panic.unwrapError;
1144/// To be deleted after zig1.wasm is updated.
1145pub const panicOutOfBounds = Panic.outOfBounds;
1146/// To be deleted after zig1.wasm is updated.
1147pub const panicStartGreaterThanEnd = Panic.startGreaterThanEnd;
1148/// To be deleted after zig1.wasm is updated.
1149pub const panicInactiveUnionField = Panic.inactiveUnionField;
1150/// To be deleted after zig1.wasm is updated.
1151pub const panic_messages = Panic.messages;
1134pub const Panic = panic;
11521135
11531136pub noinline fn returnError() void {
11541137 @branchHint(.unlikely);
lib/std/debug.zig+119-4
......@@ -21,9 +21,124 @@ pub const SelfInfo = @import("debug/SelfInfo.zig");
2121pub const Info = @import("debug/Info.zig");
2222pub const Coverage = @import("debug/Coverage.zig");
2323
24pub const FormattedPanic = @import("debug/FormattedPanic.zig");
25pub const SimplePanic = @import("debug/SimplePanic.zig");
26pub const NoPanic = @import("debug/NoPanic.zig");
24pub const simple_panic = @import("debug/simple_panic.zig");
25pub const no_panic = @import("debug/no_panic.zig");
26
27/// A fully-featured panic handler namespace which lowers all panics to calls to `panicFn`.
28/// Safety panics will use formatted printing to provide a meaningful error message.
29/// The signature of `panicFn` should match that of `defaultPanic`.
30pub fn FullPanic(comptime panicFn: fn ([]const u8, ?*std.builtin.StackTrace, ?usize) noreturn) type {
31 return struct {
32 pub const call = panicFn;
33 pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn {
34 @branchHint(.cold);
35 std.debug.panicExtra(null, @returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{
36 expected, found,
37 });
38 }
39 pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn {
40 @branchHint(.cold);
41 std.debug.panicExtra(ert, @returnAddress(), "attempt to unwrap error: {s}", .{@errorName(err)});
42 }
43 pub fn outOfBounds(index: usize, len: usize) noreturn {
44 @branchHint(.cold);
45 std.debug.panicExtra(null, @returnAddress(), "index out of bounds: index {d}, len {d}", .{ index, len });
46 }
47 pub fn startGreaterThanEnd(start: usize, end: usize) noreturn {
48 @branchHint(.cold);
49 std.debug.panicExtra(null, @returnAddress(), "start index {d} is larger than end index {d}", .{ start, end });
50 }
51 pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn {
52 @branchHint(.cold);
53 std.debug.panicExtra(null, @returnAddress(), "access of union field '{s}' while field '{s}' is active", .{
54 @tagName(accessed), @tagName(active),
55 });
56 }
57 pub fn reachedUnreachable() noreturn {
58 @branchHint(.cold);
59 call("reached unreachable code", null, @returnAddress());
60 }
61 pub fn unwrapNull() noreturn {
62 @branchHint(.cold);
63 call("attempt to use null value", null, @returnAddress());
64 }
65 pub fn castToNull() noreturn {
66 @branchHint(.cold);
67 call("cast causes pointer to be null", null, @returnAddress());
68 }
69 pub fn incorrectAlignment() noreturn {
70 @branchHint(.cold);
71 call("incorrect alignment", null, @returnAddress());
72 }
73 pub fn invalidErrorCode() noreturn {
74 @branchHint(.cold);
75 call("invalid error code", null, @returnAddress());
76 }
77 pub fn castTruncatedData() noreturn {
78 @branchHint(.cold);
79 call("integer cast truncated bits", null, @returnAddress());
80 }
81 pub fn negativeToUnsigned() noreturn {
82 @branchHint(.cold);
83 call("attempt to cast negative value to unsigned integer", null, @returnAddress());
84 }
85 pub fn integerOverflow() noreturn {
86 @branchHint(.cold);
87 call("integer overflow", null, @returnAddress());
88 }
89 pub fn shlOverflow() noreturn {
90 @branchHint(.cold);
91 call("left shift overflowed bits", null, @returnAddress());
92 }
93 pub fn shrOverflow() noreturn {
94 @branchHint(.cold);
95 call("right shift overflowed bits", null, @returnAddress());
96 }
97 pub fn divideByZero() noreturn {
98 @branchHint(.cold);
99 call("division by zero", null, @returnAddress());
100 }
101 pub fn exactDivisionRemainder() noreturn {
102 @branchHint(.cold);
103 call("exact division produced remainder", null, @returnAddress());
104 }
105 pub fn integerPartOutOfBounds() noreturn {
106 @branchHint(.cold);
107 call("integer part of floating point value out of bounds", null, @returnAddress());
108 }
109 pub fn corruptSwitch() noreturn {
110 @branchHint(.cold);
111 call("switch on corrupt value", null, @returnAddress());
112 }
113 pub fn shiftRhsTooBig() noreturn {
114 @branchHint(.cold);
115 call("shift amount is greater than the type size", null, @returnAddress());
116 }
117 pub fn invalidEnumValue() noreturn {
118 @branchHint(.cold);
119 call("invalid enum value", null, @returnAddress());
120 }
121 pub fn forLenMismatch() noreturn {
122 @branchHint(.cold);
123 call("for loop over objects with non-equal lengths", null, @returnAddress());
124 }
125 pub fn memcpyLenMismatch() noreturn {
126 @branchHint(.cold);
127 call("@memcpy arguments have non-equal lengths", null, @returnAddress());
128 }
129 pub fn memcpyAlias() noreturn {
130 @branchHint(.cold);
131 call("@memcpy arguments alias", null, @returnAddress());
132 }
133 pub fn noreturnReturned() noreturn {
134 @branchHint(.cold);
135 call("'noreturn' function returned", null, @returnAddress());
136 }
137
138 /// To be deleted after zig1.wasm update.
139 pub const messages = simple_panic.messages;
140 };
141}
27142
28143/// Unresolved source locations can be represented with a single `usize` that
29144/// corresponds to a virtual memory address of the program counter. Combined
......@@ -441,7 +556,7 @@ pub fn panicExtra(
441556 break :blk &buf;
442557 },
443558 };
444 std.builtin.Panic.call(msg, trace, ret_addr);
559 std.builtin.panic.call(msg, trace, ret_addr);
445560}
446561
447562/// Non-zero whenever the program triggered a panic.
lib/std/debug/FormattedPanic.zig deleted-45
......@@ -1,45 +0,0 @@
1//! This namespace is the default one used by the Zig compiler to emit various
2//! kinds of safety panics, due to the logic in `std.builtin.Panic`.
3//!
4//! Since Zig does not have interfaces, this file serves as an example template
5//! for users to provide their own alternative panic handling.
6//!
7//! As an alternative, see `std.debug.SimplePanic`.
8
9const std = @import("../std.zig");
10
11/// Dumps a stack trace to standard error, then aborts.
12///
13/// Explicit calls to `@panic` lower to calling this function.
14pub const call: fn ([]const u8, ?*std.builtin.StackTrace, ?usize) noreturn = std.debug.defaultPanic;
15
16pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn {
17 @branchHint(.cold);
18 std.debug.panicExtra(null, @returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{
19 expected, found,
20 });
21}
22
23pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn {
24 @branchHint(.cold);
25 std.debug.panicExtra(ert, @returnAddress(), "attempt to unwrap error: {s}", .{@errorName(err)});
26}
27
28pub fn outOfBounds(index: usize, len: usize) noreturn {
29 @branchHint(.cold);
30 std.debug.panicExtra(null, @returnAddress(), "index out of bounds: index {d}, len {d}", .{ index, len });
31}
32
33pub fn startGreaterThanEnd(start: usize, end: usize) noreturn {
34 @branchHint(.cold);
35 std.debug.panicExtra(null, @returnAddress(), "start index {d} is larger than end index {d}", .{ start, end });
36}
37
38pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn {
39 @branchHint(.cold);
40 std.debug.panicExtra(null, @returnAddress(), "access of union field '{s}' while field '{s}' is active", .{
41 @tagName(accessed), @tagName(active),
42 });
43}
44
45pub const messages = std.debug.SimplePanic.messages;
lib/std/debug/NoPanic.zig deleted-59
......@@ -1,59 +0,0 @@
1//! This namespace can be used with `pub const Panic = std.debug.NoPanic;` in the root file.
2//! It emits as little code as possible, for testing purposes.
3//!
4//! For a functional alternative, see `std.debug.FormattedPanic`.
5
6const std = @import("../std.zig");
7
8pub fn call(_: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
9 @branchHint(.cold);
10 @trap();
11}
12
13pub fn sentinelMismatch(_: anytype, _: anytype) noreturn {
14 @branchHint(.cold);
15 @trap();
16}
17
18pub fn unwrapError(_: ?*std.builtin.StackTrace, _: anyerror) noreturn {
19 @branchHint(.cold);
20 @trap();
21}
22
23pub fn outOfBounds(_: usize, _: usize) noreturn {
24 @branchHint(.cold);
25 @trap();
26}
27
28pub fn startGreaterThanEnd(_: usize, _: usize) noreturn {
29 @branchHint(.cold);
30 @trap();
31}
32
33pub fn inactiveUnionField(_: anytype, _: anytype) noreturn {
34 @branchHint(.cold);
35 @trap();
36}
37
38pub const messages = struct {
39 pub const reached_unreachable = "";
40 pub const unwrap_null = "";
41 pub const cast_to_null = "";
42 pub const incorrect_alignment = "";
43 pub const invalid_error_code = "";
44 pub const cast_truncated_data = "";
45 pub const negative_to_unsigned = "";
46 pub const integer_overflow = "";
47 pub const shl_overflow = "";
48 pub const shr_overflow = "";
49 pub const divide_by_zero = "";
50 pub const exact_division_remainder = "";
51 pub const integer_part_out_of_bounds = "";
52 pub const corrupt_switch = "";
53 pub const shift_rhs_too_big = "";
54 pub const invalid_enum_value = "";
55 pub const for_len_mismatch = "";
56 pub const memcpy_len_mismatch = "";
57 pub const memcpy_alias = "";
58 pub const noreturn_returned = "";
59};
lib/std/debug/SimplePanic.zig deleted-86
......@@ -1,86 +0,0 @@
1//! This namespace is the default one used by the Zig compiler to emit various
2//! kinds of safety panics, due to the logic in `std.builtin.Panic`.
3//!
4//! Since Zig does not have interfaces, this file serves as an example template
5//! for users to provide their own alternative panic handling.
6//!
7//! As an alternative, see `std.debug.FormattedPanic`.
8
9const std = @import("../std.zig");
10
11/// Prints the message to stderr without a newline and then traps.
12///
13/// Explicit calls to `@panic` lower to calling this function.
14pub fn call(msg: []const u8, ert: ?*std.builtin.StackTrace, ra: ?usize) noreturn {
15 @branchHint(.cold);
16 _ = ert;
17 _ = ra;
18 std.debug.lockStdErr();
19 const stderr = std.io.getStdErr();
20 stderr.writeAll(msg) catch {};
21 @trap();
22}
23
24pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn {
25 _ = found;
26 call("sentinel mismatch", null, null);
27}
28
29pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn {
30 _ = ert;
31 _ = &err;
32 call("attempt to unwrap error", null, null);
33}
34
35pub fn outOfBounds(index: usize, len: usize) noreturn {
36 _ = index;
37 _ = len;
38 call("index out of bounds", null, null);
39}
40
41pub fn startGreaterThanEnd(start: usize, end: usize) noreturn {
42 _ = start;
43 _ = end;
44 call("start index is larger than end index", null, null);
45}
46
47pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn {
48 _ = accessed;
49 call("access of inactive union field", null, null);
50}
51
52pub const messages = struct {
53 pub const reached_unreachable = "reached unreachable code";
54 pub const unwrap_null = "attempt to use null value";
55 pub const cast_to_null = "cast causes pointer to be null";
56 pub const incorrect_alignment = "incorrect alignment";
57 pub const invalid_error_code = "invalid error code";
58 pub const cast_truncated_data = "integer cast truncated bits";
59 pub const negative_to_unsigned = "attempt to cast negative value to unsigned integer";
60 pub const integer_overflow = "integer overflow";
61 pub const shl_overflow = "left shift overflowed bits";
62 pub const shr_overflow = "right shift overflowed bits";
63 pub const divide_by_zero = "division by zero";
64 pub const exact_division_remainder = "exact division produced remainder";
65 pub const integer_part_out_of_bounds = "integer part of floating point value out of bounds";
66 pub const corrupt_switch = "switch on corrupt value";
67 pub const shift_rhs_too_big = "shift amount is greater than the type size";
68 pub const invalid_enum_value = "invalid enum value";
69 pub const for_len_mismatch = "for loop over objects with non-equal lengths";
70 pub const memcpy_len_mismatch = "@memcpy arguments have non-equal lengths";
71 pub const memcpy_alias = "@memcpy arguments alias";
72 pub const noreturn_returned = "'noreturn' function returned";
73
74 /// To be deleted after zig1.wasm is updated.
75 pub const inactive_union_field = "access of inactive union field";
76 /// To be deleted after zig1.wasm is updated.
77 pub const sentinel_mismatch = "sentinel mismatch";
78 /// To be deleted after zig1.wasm is updated.
79 pub const unwrap_error = "attempt to unwrap error";
80 /// To be deleted after zig1.wasm is updated.
81 pub const index_out_of_bounds = "index out of bounds";
82 /// To be deleted after zig1.wasm is updated.
83 pub const start_index_greater_than_end = "start index is larger than end index";
84 /// To be deleted after zig1.wasm is updated.
85 pub const unreach = reached_unreachable;
86};
lib/std/debug/no_panic.zig created+160
......@@ -0,0 +1,160 @@
1//! This namespace can be used with `pub const panic = std.debug.no_panic;` in the root file.
2//! It emits as little code as possible, for testing purposes.
3//!
4//! For a functional alternative, see `std.debug.FullPanic`.
5
6const std = @import("../std.zig");
7
8pub fn call(_: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
9 @branchHint(.cold);
10 @trap();
11}
12
13pub fn sentinelMismatch(_: anytype, _: anytype) noreturn {
14 @branchHint(.cold);
15 @trap();
16}
17
18pub fn unwrapError(_: ?*std.builtin.StackTrace, _: anyerror) noreturn {
19 @branchHint(.cold);
20 @trap();
21}
22
23pub fn outOfBounds(_: usize, _: usize) noreturn {
24 @branchHint(.cold);
25 @trap();
26}
27
28pub fn startGreaterThanEnd(_: usize, _: usize) noreturn {
29 @branchHint(.cold);
30 @trap();
31}
32
33pub fn inactiveUnionField(_: anytype, _: anytype) noreturn {
34 @branchHint(.cold);
35 @trap();
36}
37
38pub fn reachedUnreachable() noreturn {
39 @branchHint(.cold);
40 @trap();
41}
42
43pub fn unwrapNull() noreturn {
44 @branchHint(.cold);
45 @trap();
46}
47
48pub fn castToNull() noreturn {
49 @branchHint(.cold);
50 @trap();
51}
52
53pub fn incorrectAlignment() noreturn {
54 @branchHint(.cold);
55 @trap();
56}
57
58pub fn invalidErrorCode() noreturn {
59 @branchHint(.cold);
60 @trap();
61}
62
63pub fn castTruncatedData() noreturn {
64 @branchHint(.cold);
65 @trap();
66}
67
68pub fn negativeToUnsigned() noreturn {
69 @branchHint(.cold);
70 @trap();
71}
72
73pub fn integerOverflow() noreturn {
74 @branchHint(.cold);
75 @trap();
76}
77
78pub fn shlOverflow() noreturn {
79 @branchHint(.cold);
80 @trap();
81}
82
83pub fn shrOverflow() noreturn {
84 @branchHint(.cold);
85 @trap();
86}
87
88pub fn divideByZero() noreturn {
89 @branchHint(.cold);
90 @trap();
91}
92
93pub fn exactDivisionRemainder() noreturn {
94 @branchHint(.cold);
95 @trap();
96}
97
98pub fn integerPartOutOfBounds() noreturn {
99 @branchHint(.cold);
100 @trap();
101}
102
103pub fn corruptSwitch() noreturn {
104 @branchHint(.cold);
105 @trap();
106}
107
108pub fn shiftRhsTooBig() noreturn {
109 @branchHint(.cold);
110 @trap();
111}
112
113pub fn invalidEnumValue() noreturn {
114 @branchHint(.cold);
115 @trap();
116}
117
118pub fn forLenMismatch() noreturn {
119 @branchHint(.cold);
120 @trap();
121}
122
123pub fn memcpyLenMismatch() noreturn {
124 @branchHint(.cold);
125 @trap();
126}
127
128pub fn memcpyAlias() noreturn {
129 @branchHint(.cold);
130 @trap();
131}
132
133pub fn noreturnReturned() noreturn {
134 @branchHint(.cold);
135 @trap();
136}
137
138/// To be deleted after zig1.wasm update.
139pub const messages = struct {
140 pub const reached_unreachable = "";
141 pub const unwrap_null = "";
142 pub const cast_to_null = "";
143 pub const incorrect_alignment = "";
144 pub const invalid_error_code = "";
145 pub const cast_truncated_data = "";
146 pub const negative_to_unsigned = "";
147 pub const integer_overflow = "";
148 pub const shl_overflow = "";
149 pub const shr_overflow = "";
150 pub const divide_by_zero = "";
151 pub const exact_division_remainder = "";
152 pub const integer_part_out_of_bounds = "";
153 pub const corrupt_switch = "";
154 pub const shift_rhs_too_big = "";
155 pub const invalid_enum_value = "";
156 pub const for_len_mismatch = "";
157 pub const memcpy_len_mismatch = "";
158 pub const memcpy_alias = "";
159 pub const noreturn_returned = "";
160};
lib/std/debug/simple_panic.zig created+154
......@@ -0,0 +1,154 @@
1//! This namespace is the default one used by the Zig compiler to emit various
2//! kinds of safety panics, due to the logic in `std.builtin.panic`.
3//!
4//! Since Zig does not have interfaces, this file serves as an example template
5//! for users to provide their own alternative panic handling.
6//!
7//! As an alternative, see `std.debug.FullPanic`.
8
9const std = @import("../std.zig");
10
11/// Prints the message to stderr without a newline and then traps.
12///
13/// Explicit calls to `@panic` lower to calling this function.
14pub fn call(msg: []const u8, ert: ?*std.builtin.StackTrace, ra: ?usize) noreturn {
15 @branchHint(.cold);
16 _ = ert;
17 _ = ra;
18 std.debug.lockStdErr();
19 const stderr = std.io.getStdErr();
20 stderr.writeAll(msg) catch {};
21 @trap();
22}
23
24pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn {
25 _ = found;
26 call("sentinel mismatch", null, null);
27}
28
29pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn {
30 _ = ert;
31 _ = &err;
32 call("attempt to unwrap error", null, null);
33}
34
35pub fn outOfBounds(index: usize, len: usize) noreturn {
36 _ = index;
37 _ = len;
38 call("index out of bounds", null, null);
39}
40
41pub fn startGreaterThanEnd(start: usize, end: usize) noreturn {
42 _ = start;
43 _ = end;
44 call("start index is larger than end index", null, null);
45}
46
47pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn {
48 _ = accessed;
49 call("access of inactive union field", null, null);
50}
51
52pub fn reachedUnreachable() noreturn {
53 call("reached unreachable code", null, null);
54}
55
56pub fn unwrapNull() noreturn {
57 call("attempt to use null value", null, null);
58}
59
60pub fn castToNull() noreturn {
61 call("cast causes pointer to be null", null, null);
62}
63
64pub fn incorrectAlignment() noreturn {
65 call("incorrect alignment", null, null);
66}
67
68pub fn invalidErrorCode() noreturn {
69 call("invalid error code", null, null);
70}
71
72pub fn castTruncatedData() noreturn {
73 call("integer cast truncated bits", null, null);
74}
75
76pub fn negativeToUnsigned() noreturn {
77 call("attempt to cast negative value to unsigned integer", null, null);
78}
79
80pub fn integerOverflow() noreturn {
81 call("integer overflow", null, null);
82}
83
84pub fn shlOverflow() noreturn {
85 call("left shift overflowed bits", null, null);
86}
87
88pub fn shrOverflow() noreturn {
89 call("right shift overflowed bits", null, null);
90}
91
92pub fn divideByZero() noreturn {
93 call("division by zero", null, null);
94}
95
96pub fn exactDivisionRemainder() noreturn {
97 call("exact division produced remainder", null, null);
98}
99
100pub fn integerPartOutOfBounds() noreturn {
101 call("integer part of floating point value out of bounds", null, null);
102}
103
104pub fn corruptSwitch() noreturn {
105 call("switch on corrupt value", null, null);
106}
107
108pub fn shiftRhsTooBig() noreturn {
109 call("shift amount is greater than the type size", null, null);
110}
111
112pub fn invalidEnumValue() noreturn {
113 call("invalid enum value", null, null);
114}
115
116pub fn forLenMismatch() noreturn {
117 call("for loop over objects with non-equal lengths", null, null);
118}
119
120pub fn memcpyLenMismatch() noreturn {
121 call("@memcpy arguments have non-equal lengths", null, null);
122}
123
124pub fn memcpyAlias() noreturn {
125 call("@memcpy arguments alias", null, null);
126}
127
128pub fn noreturnReturned() noreturn {
129 call("'noreturn' function returned", null, null);
130}
131
132/// To be deleted after zig1.wasm update.
133pub const messages = struct {
134 pub const reached_unreachable = "reached unreachable code";
135 pub const unwrap_null = "attempt to use null value";
136 pub const cast_to_null = "cast causes pointer to be null";
137 pub const incorrect_alignment = "incorrect alignment";
138 pub const invalid_error_code = "invalid error code";
139 pub const cast_truncated_data = "integer cast truncated bits";
140 pub const negative_to_unsigned = "attempt to cast negative value to unsigned integer";
141 pub const integer_overflow = "integer overflow";
142 pub const shl_overflow = "left shift overflowed bits";
143 pub const shr_overflow = "right shift overflowed bits";
144 pub const divide_by_zero = "division by zero";
145 pub const exact_division_remainder = "exact division produced remainder";
146 pub const integer_part_out_of_bounds = "integer part of floating point value out of bounds";
147 pub const corrupt_switch = "switch on corrupt value";
148 pub const shift_rhs_too_big = "shift amount is greater than the type size";
149 pub const invalid_enum_value = "invalid enum value";
150 pub const for_len_mismatch = "for loop over objects with non-equal lengths";
151 pub const memcpy_len_mismatch = "@memcpy arguments have non-equal lengths";
152 pub const memcpy_alias = "@memcpy arguments alias";
153 pub const noreturn_returned = "'noreturn' function returned";
154};
lib/std/meta.zig+1-2
......@@ -448,8 +448,7 @@ pub fn fieldNames(comptime T: type) *const [fields(T).len][:0]const u8 {
448448 return comptime blk: {
449449 const fieldInfos = fields(T);
450450 var names: [fieldInfos.len][:0]const u8 = undefined;
451 // This concat can be removed with the next zig1 update.
452 for (&names, fieldInfos) |*name, field| name.* = field.name ++ "";
451 for (&names, fieldInfos) |*name, field| name.* = field.name;
453452 const final = names;
454453 break :blk &final;
455454 };
src/Sema.zig+89-66
......@@ -5918,13 +5918,14 @@ fn zirCompileLog(
59185918}
59195919
59205920fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
5921 const pt = sema.pt;
5922 const zcu = pt.zcu;
5923
59215924 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
59225925 const src = block.nodeOffset(inst_data.src_node);
59235926 const msg_inst = try sema.resolveInst(inst_data.operand);
59245927
5925 // `panicWithMsg` would perform this coercion for us, but we can get a better
5926 // source location if we do it here.
5927 const coerced_msg = try sema.coerce(block, Type.slice_const_u8, msg_inst, block.builtinCallArgSrc(inst_data.src_node, 0));
5928 const coerced_msg = try sema.coerce(block, .slice_const_u8, msg_inst, block.builtinCallArgSrc(inst_data.src_node, 0));
59285929
59295930 if (block.isComptime()) {
59305931 return sema.fail(block, src, "encountered @panic at comptime", .{});
......@@ -5936,7 +5937,23 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
59365937 sema.branch_hint = .cold;
59375938 }
59385939
5939 try sema.panicWithMsg(block, src, coerced_msg, .@"@panic");
5940 if (!zcu.backendSupportsFeature(.panic_fn)) {
5941 _ = try block.addNoOp(.trap);
5942 return;
5943 }
5944
5945 try sema.ensureMemoizedStateResolved(src, .panic);
5946 try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"panic.call"));
5947
5948 const panic_fn = Air.internedToRef(zcu.builtin_decl_values.get(.@"panic.call"));
5949 const null_stack_trace = Air.internedToRef(zcu.null_stack_trace);
5950
5951 const opt_usize_ty = try pt.optionalType(.usize_type);
5952 const null_ret_addr = Air.internedToRef((try pt.intern(.{ .opt = .{
5953 .ty = opt_usize_ty.toIntern(),
5954 .val = .none,
5955 } })));
5956 try sema.callBuiltin(block, src, panic_fn, .auto, &.{ coerced_msg, null_stack_trace, null_ret_addr }, .@"@panic");
59405957}
59415958
59425959fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
......@@ -13787,7 +13804,7 @@ fn maybeErrorUnwrap(
1378713804 const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
1378813805 const msg_inst = try sema.resolveInst(inst_data.operand);
1378913806
13790 const panic_fn = try getBuiltin(sema, operand_src, .@"Panic.call");
13807 const panic_fn = try getBuiltin(sema, operand_src, .@"panic.call");
1379113808 const err_return_trace = try sema.getErrorReturnTrace(block);
1379213809 const args: [3]Air.Inst.Ref = .{ msg_inst, err_return_trace, .null_value };
1379313810 try sema.callBuiltin(block, operand_src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check");
......@@ -27083,15 +27100,16 @@ fn explainWhyTypeIsNotPacked(
2708327100/// Backends depend on panic decls being available when lowering safety-checked
2708427101/// instructions. This function ensures the panic function will be available to
2708527102/// be called during that time.
27086fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.PanicId) !InternPool.Index {
27103fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !InternPool.Index {
2708727104 const zcu = sema.pt.zcu;
2708827105 try sema.ensureMemoizedStateResolved(src, .panic);
27089 try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"Panic.call"));
27106 const panic_func = zcu.builtin_decl_values.get(panic_id.toBuiltin());
27107 try zcu.ensureFuncBodyAnalysisQueued(panic_func);
2709027108 switch (sema.owner.unwrap()) {
2709127109 .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {},
2709227110 .func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(owner_func, true),
2709327111 }
27094 return zcu.builtin_decl_values.get(panic_id.toBuiltin());
27112 return panic_func;
2709527113}
2709627114
2709727115fn addSafetyCheck(
......@@ -27099,7 +27117,7 @@ fn addSafetyCheck(
2709927117 parent_block: *Block,
2710027118 src: LazySrcLoc,
2710127119 ok: Air.Inst.Ref,
27102 panic_id: Zcu.PanicId,
27120 panic_id: Zcu.SimplePanicId,
2710327121) !void {
2710427122 const gpa = sema.gpa;
2710527123 assert(!parent_block.isComptime());
......@@ -27186,29 +27204,6 @@ fn addSafetyCheckExtra(
2718627204 parent_block.instructions.appendAssumeCapacity(block_inst);
2718727205}
2718827206
27189fn panicWithMsg(sema: *Sema, block: *Block, src: LazySrcLoc, msg_inst: Air.Inst.Ref, operation: CallOperation) !void {
27190 const pt = sema.pt;
27191 const zcu = pt.zcu;
27192
27193 if (!zcu.backendSupportsFeature(.panic_fn)) {
27194 _ = try block.addNoOp(.trap);
27195 return;
27196 }
27197
27198 try sema.ensureMemoizedStateResolved(src, .panic);
27199 try zcu.ensureFuncBodyAnalysisQueued(zcu.builtin_decl_values.get(.@"Panic.call"));
27200
27201 const panic_fn = Air.internedToRef(zcu.builtin_decl_values.get(.@"Panic.call"));
27202 const null_stack_trace = Air.internedToRef(zcu.null_stack_trace);
27203
27204 const opt_usize_ty = try pt.optionalType(.usize_type);
27205 const null_ret_addr = Air.internedToRef((try pt.intern(.{ .opt = .{
27206 .ty = opt_usize_ty.toIntern(),
27207 .val = .none,
27208 } })));
27209 try sema.callBuiltin(block, src, panic_fn, .auto, &.{ msg_inst, null_stack_trace, null_ret_addr }, operation);
27210}
27211
2721227207fn addSafetyCheckUnwrapError(
2721327208 sema: *Sema,
2721427209 parent_block: *Block,
......@@ -27246,7 +27241,7 @@ fn safetyPanicUnwrapError(sema: *Sema, block: *Block, src: LazySrcLoc, err: Air.
2724627241 if (!zcu.backendSupportsFeature(.panic_fn)) {
2724727242 _ = try block.addNoOp(.trap);
2724827243 } else {
27249 const panic_fn = try getBuiltin(sema, src, .@"Panic.unwrapError");
27244 const panic_fn = try getBuiltin(sema, src, .@"panic.unwrapError");
2725027245 const err_return_trace = try sema.getErrorReturnTrace(block);
2725127246 const args: [2]Air.Inst.Ref = .{ err_return_trace, err };
2725227247 try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check");
......@@ -27263,7 +27258,7 @@ fn addSafetyCheckIndexOob(
2726327258) !void {
2726427259 assert(!parent_block.isComptime());
2726527260 const ok = try parent_block.addBinOp(cmp_op, index, len);
27266 return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.outOfBounds", &.{ index, len });
27261 return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.outOfBounds", &.{ index, len });
2726727262}
2726827263
2726927264fn addSafetyCheckInactiveUnionField(
......@@ -27275,7 +27270,7 @@ fn addSafetyCheckInactiveUnionField(
2727527270) !void {
2727627271 assert(!parent_block.isComptime());
2727727272 const ok = try parent_block.addBinOp(.cmp_eq, active_tag, wanted_tag);
27278 return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.inactiveUnionField", &.{ active_tag, wanted_tag });
27273 return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.inactiveUnionField", &.{ active_tag, wanted_tag });
2727927274}
2728027275
2728127276fn addSafetyCheckSentinelMismatch(
......@@ -27316,7 +27311,7 @@ fn addSafetyCheckSentinelMismatch(
2731627311 break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel);
2731727312 };
2731827313
27319 return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.sentinelMismatch", &.{
27314 return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.sentinelMismatch", &.{
2732027315 expected_sentinel, actual_sentinel,
2732127316 });
2732227317}
......@@ -27358,9 +27353,13 @@ fn addSafetyCheckCall(
2735827353}
2735927354
2736027355/// This does not set `sema.branch_hint`.
27361fn safetyPanic(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.PanicId) CompileError!void {
27362 const msg_val = try sema.preparePanicId(src, panic_id);
27363 try sema.panicWithMsg(block, src, Air.internedToRef(msg_val), .@"safety check");
27356fn safetyPanic(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) CompileError!void {
27357 if (!sema.pt.zcu.backendSupportsFeature(.panic_fn)) {
27358 _ = try block.addNoOp(.trap);
27359 } else {
27360 const panic_fn = try sema.preparePanicId(src, panic_id);
27361 try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &.{}, .@"safety check");
27362 }
2736427363}
2736527364
2736627365fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void {
......@@ -32818,7 +32817,7 @@ fn analyzeSlice(
3281832817 assert(!block.isComptime());
3281932818 try sema.requireRuntimeBlock(block, src, runtime_src.?);
3282032819 const ok = try block.addBinOp(.cmp_lte, start, end);
32821 try sema.addSafetyCheckCall(block, src, ok, .@"Panic.startGreaterThanEnd", &.{ start, end });
32820 try sema.addSafetyCheckCall(block, src, ok, .@"panic.startGreaterThanEnd", &.{ start, end });
3282232821 }
3282332822 const new_len = if (by_length)
3282432823 try sema.coerce(block, Type.usize, uncasted_end_opt, end_src)
......@@ -38525,14 +38524,9 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc,
3852538524 break :val uncoerced_val;
3852638525 },
3852738526 .func => val: {
38528 if (try sema.getExpectedBuiltinFnType(src, builtin_decl)) |func_ty| {
38529 const coerced = try sema.coerce(block, func_ty, Air.internedToRef(uncoerced_val.toIntern()), src);
38530 break :val .fromInterned(coerced.toInterned().?);
38531 }
38532 if (uncoerced_val.typeOf(zcu).zigTypeTag(zcu) != .@"fn") {
38533 return sema.fail(block, src, "{s}.{s} is not a function", .{ parent_name, name });
38534 }
38535 break :val uncoerced_val;
38527 const func_ty = try sema.getExpectedBuiltinFnType(src, builtin_decl);
38528 const coerced = try sema.coerce(block, func_ty, Air.internedToRef(uncoerced_val.toIntern()), src);
38529 break :val .fromInterned(coerced.toInterned().?);
3853638530 },
3853738531 .string => val: {
3853838532 const coerced = try sema.coerce(block, .slice_const_u8, Air.internedToRef(uncoerced_val.toIntern()), src);
......@@ -38567,16 +38561,19 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc,
3856738561 return any_changed;
3856838562}
3856938563
38570/// Given that `decl.kind() == .func`, get the type expected of the function if necessary.
38571/// If this will be type checked by `Sema` anyway, this function may return `null`. In
38572/// particular, generic functions should return `null`, as `Sema` will necessarily check
38573/// them at instantiation time. Returning non-null is necessary only when backends can emit
38574/// calls to the function, as is the case with the panic handler.
38575fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) CompileError!?Type {
38564/// Given that `decl.kind() == .func`, get the type expected of the function.
38565fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) CompileError!Type {
3857638566 const pt = sema.pt;
3857738567 return switch (decl) {
38568 // `noinline fn () void`
38569 .returnError => try pt.funcType(.{
38570 .param_types = &.{},
38571 .return_type = .void_type,
38572 .is_noinline = true,
38573 }),
38574
3857838575 // `fn ([]const u8, ?*StackTrace, ?usize) noreturn`
38579 .@"Panic.call" => try pt.funcType(.{
38576 .@"panic.call" => try pt.funcType(.{
3858038577 .param_types = &.{
3858138578 .slice_const_u8_type,
3858238579 (try pt.optionalType(
......@@ -38589,8 +38586,17 @@ fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl)
3858938586 .return_type = .noreturn_type,
3859038587 }),
3859138588
38589 // `fn (anytype, anytype) noreturn`
38590 .@"panic.sentinelMismatch",
38591 .@"panic.inactiveUnionField",
38592 => try pt.funcType(.{
38593 .param_types = &.{ .generic_poison_type, .generic_poison_type },
38594 .return_type = .noreturn_type,
38595 .is_generic = true,
38596 }),
38597
3859238598 // `fn (?*StackTrace, anyerror) noreturn`
38593 .@"Panic.unwrapError" => try pt.funcType(.{
38599 .@"panic.unwrapError" => try pt.funcType(.{
3859438600 .param_types = &.{
3859538601 (try pt.optionalType(
3859638602 (try pt.singleMutPtrType(
......@@ -38603,21 +38609,38 @@ fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl)
3860338609 }),
3860438610
3860538611 // `fn (usize, usize) noreturn`
38606 .@"Panic.outOfBounds",
38607 .@"Panic.startGreaterThanEnd",
38612 .@"panic.outOfBounds",
38613 .@"panic.startGreaterThanEnd",
3860838614 => try pt.funcType(.{
3860938615 .param_types = &.{ .usize_type, .usize_type },
3861038616 .return_type = .noreturn_type,
3861138617 }),
3861238618
38613 // Generic functions, so calls are necessarily validated by Sema
38614 .@"Panic.sentinelMismatch",
38615 .@"Panic.inactiveUnionField",
38616 => null,
38617
38618 // Other functions called exclusively by Sema
38619 .returnError,
38620 => null,
38619 // `fn () noreturn`
38620 .@"panic.reachedUnreachable",
38621 .@"panic.unwrapNull",
38622 .@"panic.castToNull",
38623 .@"panic.incorrectAlignment",
38624 .@"panic.invalidErrorCode",
38625 .@"panic.castTruncatedData",
38626 .@"panic.negativeToUnsigned",
38627 .@"panic.integerOverflow",
38628 .@"panic.shlOverflow",
38629 .@"panic.shrOverflow",
38630 .@"panic.divideByZero",
38631 .@"panic.exactDivisionRemainder",
38632 .@"panic.integerPartOutOfBounds",
38633 .@"panic.corruptSwitch",
38634 .@"panic.shiftRhsTooBig",
38635 .@"panic.invalidEnumValue",
38636 .@"panic.forLenMismatch",
38637 .@"panic.memcpyLenMismatch",
38638 .@"panic.memcpyAlias",
38639 .@"panic.noreturnReturned",
38640 => try pt.funcType(.{
38641 .param_types = &.{},
38642 .return_type = .noreturn_type,
38643 }),
3862138644
3862238645 else => unreachable,
3862338646 };
src/Zcu.zig+81-74
......@@ -269,34 +269,33 @@ pub const BuiltinDecl = enum {
269269 @"Type.Opaque",
270270 @"Type.Declaration",
271271
272 Panic,
273 @"Panic.call",
274 @"Panic.sentinelMismatch",
275 @"Panic.unwrapError",
276 @"Panic.outOfBounds",
277 @"Panic.startGreaterThanEnd",
278 @"Panic.inactiveUnionField",
279 @"Panic.messages",
280 @"Panic.messages.reached_unreachable",
281 @"Panic.messages.unwrap_null",
282 @"Panic.messages.cast_to_null",
283 @"Panic.messages.incorrect_alignment",
284 @"Panic.messages.invalid_error_code",
285 @"Panic.messages.cast_truncated_data",
286 @"Panic.messages.negative_to_unsigned",
287 @"Panic.messages.integer_overflow",
288 @"Panic.messages.shl_overflow",
289 @"Panic.messages.shr_overflow",
290 @"Panic.messages.divide_by_zero",
291 @"Panic.messages.exact_division_remainder",
292 @"Panic.messages.integer_part_out_of_bounds",
293 @"Panic.messages.corrupt_switch",
294 @"Panic.messages.shift_rhs_too_big",
295 @"Panic.messages.invalid_enum_value",
296 @"Panic.messages.for_len_mismatch",
297 @"Panic.messages.memcpy_len_mismatch",
298 @"Panic.messages.memcpy_alias",
299 @"Panic.messages.noreturn_returned",
272 panic,
273 @"panic.call",
274 @"panic.sentinelMismatch",
275 @"panic.unwrapError",
276 @"panic.outOfBounds",
277 @"panic.startGreaterThanEnd",
278 @"panic.inactiveUnionField",
279 @"panic.reachedUnreachable",
280 @"panic.unwrapNull",
281 @"panic.castToNull",
282 @"panic.incorrectAlignment",
283 @"panic.invalidErrorCode",
284 @"panic.castTruncatedData",
285 @"panic.negativeToUnsigned",
286 @"panic.integerOverflow",
287 @"panic.shlOverflow",
288 @"panic.shrOverflow",
289 @"panic.divideByZero",
290 @"panic.exactDivisionRemainder",
291 @"panic.integerPartOutOfBounds",
292 @"panic.corruptSwitch",
293 @"panic.shiftRhsTooBig",
294 @"panic.invalidEnumValue",
295 @"panic.forLenMismatch",
296 @"panic.memcpyLenMismatch",
297 @"panic.memcpyAlias",
298 @"panic.noreturnReturned",
300299
301300 VaList,
302301
......@@ -345,39 +344,35 @@ pub const BuiltinDecl = enum {
345344 .@"Type.Declaration",
346345 => .type,
347346
348 .Panic => .type,
349
350 .@"Panic.call",
351 .@"Panic.sentinelMismatch",
352 .@"Panic.unwrapError",
353 .@"Panic.outOfBounds",
354 .@"Panic.startGreaterThanEnd",
355 .@"Panic.inactiveUnionField",
347 .panic => .type,
348
349 .@"panic.call",
350 .@"panic.sentinelMismatch",
351 .@"panic.unwrapError",
352 .@"panic.outOfBounds",
353 .@"panic.startGreaterThanEnd",
354 .@"panic.inactiveUnionField",
355 .@"panic.reachedUnreachable",
356 .@"panic.unwrapNull",
357 .@"panic.castToNull",
358 .@"panic.incorrectAlignment",
359 .@"panic.invalidErrorCode",
360 .@"panic.castTruncatedData",
361 .@"panic.negativeToUnsigned",
362 .@"panic.integerOverflow",
363 .@"panic.shlOverflow",
364 .@"panic.shrOverflow",
365 .@"panic.divideByZero",
366 .@"panic.exactDivisionRemainder",
367 .@"panic.integerPartOutOfBounds",
368 .@"panic.corruptSwitch",
369 .@"panic.shiftRhsTooBig",
370 .@"panic.invalidEnumValue",
371 .@"panic.forLenMismatch",
372 .@"panic.memcpyLenMismatch",
373 .@"panic.memcpyAlias",
374 .@"panic.noreturnReturned",
356375 => .func,
357
358 .@"Panic.messages" => .type,
359
360 .@"Panic.messages.reached_unreachable",
361 .@"Panic.messages.unwrap_null",
362 .@"Panic.messages.cast_to_null",
363 .@"Panic.messages.incorrect_alignment",
364 .@"Panic.messages.invalid_error_code",
365 .@"Panic.messages.cast_truncated_data",
366 .@"Panic.messages.negative_to_unsigned",
367 .@"Panic.messages.integer_overflow",
368 .@"Panic.messages.shl_overflow",
369 .@"Panic.messages.shr_overflow",
370 .@"Panic.messages.divide_by_zero",
371 .@"Panic.messages.exact_division_remainder",
372 .@"Panic.messages.integer_part_out_of_bounds",
373 .@"Panic.messages.corrupt_switch",
374 .@"Panic.messages.shift_rhs_too_big",
375 .@"Panic.messages.invalid_enum_value",
376 .@"Panic.messages.for_len_mismatch",
377 .@"Panic.messages.memcpy_len_mismatch",
378 .@"Panic.messages.memcpy_alias",
379 .@"Panic.messages.noreturn_returned",
380 => .string,
381376 };
382377 }
383378
......@@ -423,7 +418,7 @@ pub const BuiltinDecl = enum {
423418 const Memoized = std.enums.EnumArray(BuiltinDecl, InternPool.Index);
424419};
425420
426pub const PanicId = enum {
421pub const SimplePanicId = enum {
427422 reached_unreachable,
428423 unwrap_null,
429424 cast_to_null,
......@@ -445,19 +440,31 @@ pub const PanicId = enum {
445440 memcpy_alias,
446441 noreturn_returned,
447442
448 pub fn toBuiltin(id: PanicId) BuiltinDecl {
449 const first_msg: PanicId = @enumFromInt(0);
450 const first_decl = @field(BuiltinDecl, "Panic.messages." ++ @tagName(first_msg));
451 comptime {
452 // Ensure that the messages are ordered the same in `BuiltinDecl` as they are here.
453 for (@typeInfo(PanicId).@"enum".fields) |panic_field| {
454 const expect_name = "Panic.messages." ++ panic_field.name;
455 const expect_idx = @intFromEnum(first_decl) + panic_field.value;
456 const actual_idx = @intFromEnum(@field(BuiltinDecl, expect_name));
457 assert(expect_idx == actual_idx);
458 }
459 }
460 return @enumFromInt(@intFromEnum(first_decl) + @intFromEnum(id));
443 pub fn toBuiltin(id: SimplePanicId) BuiltinDecl {
444 return switch (id) {
445 // zig fmt: off
446 .reached_unreachable => .@"panic.reachedUnreachable",
447 .unwrap_null => .@"panic.unwrapNull",
448 .cast_to_null => .@"panic.castToNull",
449 .incorrect_alignment => .@"panic.incorrectAlignment",
450 .invalid_error_code => .@"panic.invalidErrorCode",
451 .cast_truncated_data => .@"panic.castTruncatedData",
452 .negative_to_unsigned => .@"panic.negativeToUnsigned",
453 .integer_overflow => .@"panic.integerOverflow",
454 .shl_overflow => .@"panic.shlOverflow",
455 .shr_overflow => .@"panic.shrOverflow",
456 .divide_by_zero => .@"panic.divideByZero",
457 .exact_division_remainder => .@"panic.exactDivisionRemainder",
458 .integer_part_out_of_bounds => .@"panic.integerPartOutOfBounds",
459 .corrupt_switch => .@"panic.corruptSwitch",
460 .shift_rhs_too_big => .@"panic.shiftRhsTooBig",
461 .invalid_enum_value => .@"panic.invalidEnumValue",
462 .for_len_mismatch => .@"panic.forLenMismatch",
463 .memcpy_len_mismatch => .@"panic.memcpyLenMismatch",
464 .memcpy_alias => .@"panic.memcpyAlias",
465 .noreturn_returned => .@"panic.noreturnReturned",
466 // zig fmt: on
467 };
461468 }
462469};
463470
src/Zcu/PerThread.zig+1-1
......@@ -605,7 +605,7 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized
605605 // We use an arbitrary element to check if the state has been resolved yet.
606606 const to_check: Zcu.BuiltinDecl = switch (stage) {
607607 .main => .Type,
608 .panic => .Panic,
608 .panic => .panic,
609609 .va_list => .VaList,
610610 };
611611 if (zcu.builtin_decl_values.get(to_check) != .none) return;
src/codegen/llvm.zig+5-44
......@@ -5019,18 +5019,6 @@ pub const FuncGen = struct {
50195019 );
50205020 }
50215021
5022 fn resolveNullOptUsize(self: *FuncGen) Error!Builder.Constant {
5023 const o = self.ng.object;
5024 const pt = o.pt;
5025 if (o.null_opt_usize == .no_init) {
5026 o.null_opt_usize = try self.resolveValue(Value.fromInterned(try pt.intern(.{ .opt = .{
5027 .ty = try pt.intern(.{ .opt_type = .usize_type }),
5028 .val = .none,
5029 } })));
5030 }
5031 return o.null_opt_usize;
5032 }
5033
50345022 fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air.CoveragePoint) Error!void {
50355023 const o = self.ng.object;
50365024 const zcu = o.pt.zcu;
......@@ -5732,30 +5720,14 @@ pub const FuncGen = struct {
57325720 }
57335721 }
57345722
5735 fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.PanicId) !void {
5723 fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) !void {
57365724 const o = fg.ng.object;
57375725 const zcu = o.pt.zcu;
5738 const ip = &zcu.intern_pool;
5739 const msg_len: u64, const msg_ptr: Builder.Constant = msg: {
5740 const str_val = zcu.builtin_decl_values.get(panic_id.toBuiltin());
5741 assert(str_val != .none);
5742 const slice = ip.indexToKey(str_val).slice;
5743 break :msg .{ Value.fromInterned(slice.len).toUnsignedInt(zcu), try o.lowerValue(slice.ptr) };
5744 };
5745 const null_opt_addr_global = try fg.resolveNullOptUsize();
57465726 const target = zcu.getTarget();
5747 const llvm_usize = try o.lowerType(Type.usize);
5748 // example:
5749 // call fastcc void @test2.panic(
5750 // ptr @builtin.panic_messages.integer_overflow__anon_987, ; msg.ptr
5751 // i64 16, ; msg.len
5752 // ptr null, ; stack trace
5753 // ptr @2, ; addr (null ?usize)
5754 // )
5755 const panic_func = zcu.funcInfo(zcu.builtin_decl_values.get(.@"Panic.call"));
5756 const panic_nav = ip.getNav(panic_func.owner_nav);
5757 const fn_info = zcu.typeToFunc(Type.fromInterned(panic_nav.typeOf(ip))).?;
5727 const panic_func = zcu.funcInfo(zcu.builtin_decl_values.get(panic_id.toBuiltin()));
5728 const fn_info = zcu.typeToFunc(.fromInterned(panic_func.ty)).?;
57585729 const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav);
5730
57595731 const has_err_trace = zcu.comp.config.any_error_tracing and fn_info.cc == .auto;
57605732 if (has_err_trace) assert(fg.err_ret_trace != .none);
57615733 _ = try fg.wip.callIntrinsicAssumeCold();
......@@ -5765,18 +5737,7 @@ pub const FuncGen = struct {
57655737 .none,
57665738 panic_global.typeOf(&o.builder),
57675739 panic_global.toValue(&o.builder),
5768 if (has_err_trace) &.{
5769 fg.err_ret_trace,
5770 msg_ptr.toValue(),
5771 try o.builder.intValue(llvm_usize, msg_len),
5772 try o.builder.nullValue(.ptr),
5773 null_opt_addr_global.toValue(),
5774 } else &.{
5775 msg_ptr.toValue(),
5776 try o.builder.intValue(llvm_usize, msg_len),
5777 try o.builder.nullValue(.ptr),
5778 null_opt_addr_global.toValue(),
5779 },
5740 if (has_err_trace) &.{fg.err_ret_trace} else &.{},
57805741 "",
57815742 );
57825743 _ = try fg.wip.@"unreachable"();
src/crash_report.zig+5-11
......@@ -18,18 +18,12 @@ const dev = @import("dev.zig");
1818/// To use these crash report diagnostics, publish this panic in your main file
1919/// and add `pub const enable_segfault_handler = false;` to your `std_options`.
2020/// You will also need to call initialize() on startup, preferably as the very first operation in your program.
21pub const Panic = if (build_options.enable_debug_extensions) struct {
22 pub const call = compilerPanic;
23 pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
24 pub const unwrapError = std.debug.FormattedPanic.unwrapError;
25 pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
26 pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
27 pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
28 pub const messages = std.debug.FormattedPanic.messages;
29} else if (dev.env == .bootstrap)
30 std.debug.SimplePanic
21pub const panic = if (build_options.enable_debug_extensions)
22 std.debug.FullPanic(compilerPanic)
23else if (dev.env == .bootstrap)
24 std.debug.simple_panic
3125else
32 std.debug.FormattedPanic;
26 std.debug.FullPanic(std.debug.defaultPanic);
3327
3428/// Install signal handlers to identify crashes and report diagnostics.
3529pub fn initialize() void {
src/main.zig+1-1
......@@ -56,7 +56,7 @@ pub const std_options: std.Options = .{
5656 },
5757};
5858
59pub const Panic = crash_report.Panic;
59pub const panic = crash_report.panic;
6060
6161var wasi_preopens: fs.wasi.Preopens = undefined;
6262pub fn wasi_cwd() std.os.wasi.fd_t {
test/cases/compile_errors/bad_panic_call_signature.zig created+46
......@@ -0,0 +1,46 @@
1const simple_panic = std.debug.simple_panic;
2pub const panic = struct {
3 pub fn call(msg: []const u8, bad1: usize, bad2: void) noreturn {
4 _ = msg;
5 _ = bad1;
6 _ = bad2;
7 @trap();
8 }
9 pub const sentinelMismatch = simple_panic.sentinelMismatch;
10 pub const unwrapError = simple_panic.unwrapError;
11 pub const outOfBounds = simple_panic.outOfBounds;
12 pub const startGreaterThanEnd = simple_panic.startGreaterThanEnd;
13 pub const inactiveUnionField = simple_panic.inactiveUnionField;
14 pub const reachedUnreachable = simple_panic.reachedUnreachable;
15 pub const unwrapNull = simple_panic.unwrapNull;
16 pub const castToNull = simple_panic.castToNull;
17 pub const incorrectAlignment = simple_panic.incorrectAlignment;
18 pub const invalidErrorCode = simple_panic.invalidErrorCode;
19 pub const castTruncatedData = simple_panic.castTruncatedData;
20 pub const negativeToUnsigned = simple_panic.negativeToUnsigned;
21 pub const integerOverflow = simple_panic.integerOverflow;
22 pub const shlOverflow = simple_panic.shlOverflow;
23 pub const shrOverflow = simple_panic.shrOverflow;
24 pub const divideByZero = simple_panic.divideByZero;
25 pub const exactDivisionRemainder = simple_panic.exactDivisionRemainder;
26 pub const integerPartOutOfBounds = simple_panic.integerPartOutOfBounds;
27 pub const corruptSwitch = simple_panic.corruptSwitch;
28 pub const shiftRhsTooBig = simple_panic.shiftRhsTooBig;
29 pub const invalidEnumValue = simple_panic.invalidEnumValue;
30 pub const forLenMismatch = simple_panic.forLenMismatch;
31 pub const memcpyLenMismatch = simple_panic.memcpyLenMismatch;
32 pub const memcpyAlias = simple_panic.memcpyAlias;
33 pub const noreturnReturned = simple_panic.noreturnReturned;
34};
35
36export fn foo(a: u8) void {
37 @setRuntimeSafety(true);
38 _ = a + 1; // safety check to reference the panic handler
39}
40
41const std = @import("std");
42
43// error
44//
45// :3:9: error: expected type 'fn ([]const u8, ?*builtin.StackTrace, ?usize) noreturn', found 'fn ([]const u8, usize, void) noreturn'
46// :3:9: note: parameter 1 'usize' cannot cast into '?*builtin.StackTrace'
test/cases/compile_errors/bad_panic_generic_signature.zig created+41
......@@ -0,0 +1,41 @@
1const simple_panic = std.debug.simple_panic;
2pub const panic = struct {
3 pub fn sentinelMismatch() void {} // invalid
4 pub const call = simple_panic.call;
5 pub const unwrapError = simple_panic.unwrapError;
6 pub const outOfBounds = simple_panic.outOfBounds;
7 pub const startGreaterThanEnd = simple_panic.startGreaterThanEnd;
8 pub const inactiveUnionField = simple_panic.inactiveUnionField;
9 pub const reachedUnreachable = simple_panic.reachedUnreachable;
10 pub const unwrapNull = simple_panic.unwrapNull;
11 pub const castToNull = simple_panic.castToNull;
12 pub const incorrectAlignment = simple_panic.incorrectAlignment;
13 pub const invalidErrorCode = simple_panic.invalidErrorCode;
14 pub const castTruncatedData = simple_panic.castTruncatedData;
15 pub const negativeToUnsigned = simple_panic.negativeToUnsigned;
16 pub const integerOverflow = simple_panic.integerOverflow;
17 pub const shlOverflow = simple_panic.shlOverflow;
18 pub const shrOverflow = simple_panic.shrOverflow;
19 pub const divideByZero = simple_panic.divideByZero;
20 pub const exactDivisionRemainder = simple_panic.exactDivisionRemainder;
21 pub const integerPartOutOfBounds = simple_panic.integerPartOutOfBounds;
22 pub const corruptSwitch = simple_panic.corruptSwitch;
23 pub const shiftRhsTooBig = simple_panic.shiftRhsTooBig;
24 pub const invalidEnumValue = simple_panic.invalidEnumValue;
25 pub const forLenMismatch = simple_panic.forLenMismatch;
26 pub const memcpyLenMismatch = simple_panic.memcpyLenMismatch;
27 pub const memcpyAlias = simple_panic.memcpyAlias;
28 pub const noreturnReturned = simple_panic.noreturnReturned;
29};
30
31export fn foo(arr: *const [2]u8) void {
32 @setRuntimeSafety(true);
33 _ = arr[0..1 :0];
34}
35
36const std = @import("std");
37
38// error
39//
40// :3:9: error: expected type 'fn (anytype, anytype) noreturn', found 'fn () void'
41// :3:9: note: non-generic function cannot cast into a generic function
test/cases/compile_errors/bad_panic_signature.zig deleted-28
......@@ -1,28 +0,0 @@
1pub const Panic = struct {
2 pub const call = badPanicSignature;
3 pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
4 pub const unwrapError = std.debug.FormattedPanic.unwrapError;
5 pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
6 pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
7 pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
8 pub const messages = std.debug.FormattedPanic.messages;
9};
10
11fn badPanicSignature(msg: []const u8, bad1: usize, bad2: void) noreturn {
12 _ = msg;
13 _ = bad1;
14 _ = bad2;
15 @trap();
16}
17
18export fn foo(a: u8) void {
19 @setRuntimeSafety(true);
20 _ = a + 1; // safety check to reference the panic handler
21}
22
23const std = @import("std");
24
25// error
26//
27// :2:9: error: expected type 'fn ([]const u8, ?*builtin.StackTrace, ?usize) noreturn', found 'fn ([]const u8, usize, void) noreturn'
28// :2:9: note: parameter 1 'usize' cannot cast into '?*builtin.StackTrace'
test/incremental/change_panic_handler+3-27
......@@ -9,15 +9,7 @@ pub fn main() !u8 {
99 _ = a + 1;
1010 return 1;
1111}
12pub const Panic = struct {
13 pub const call = myPanic;
14 pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
15 pub const unwrapError = std.debug.FormattedPanic.unwrapError;
16 pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
17 pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
18 pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
19 pub const messages = std.debug.FormattedPanic.messages;
20};
12pub const panic = std.debug.FullPanic(myPanic);
2113fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
2214 std.io.getStdOut().writer().print("panic message: {s}\n", .{msg}) catch {};
2315 std.process.exit(0);
......@@ -33,15 +25,7 @@ pub fn main() !u8 {
3325 _ = a + 1;
3426 return 1;
3527}
36pub const Panic = struct {
37 pub const call = myPanic;
38 pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
39 pub const unwrapError = std.debug.FormattedPanic.unwrapError;
40 pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
41 pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
42 pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
43 pub const messages = std.debug.FormattedPanic.messages;
44};
28pub const panic = std.debug.FullPanic(myPanic);
4529fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4630 std.io.getStdOut().writer().print("new panic message: {s}\n", .{msg}) catch {};
4731 std.process.exit(0);
......@@ -57,15 +41,7 @@ pub fn main() !u8 {
5741 _ = a + 1;
5842 return 1;
5943}
60pub const Panic = struct {
61 pub const call = myPanicNew;
62 pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch;
63 pub const unwrapError = std.debug.FormattedPanic.unwrapError;
64 pub const outOfBounds = std.debug.FormattedPanic.outOfBounds;
65 pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd;
66 pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField;
67 pub const messages = std.debug.FormattedPanic.messages;
68};
44pub const panic = std.debug.FullPanic(myPanicNew);
6945fn myPanicNew(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
7046 std.io.getStdOut().writer().print("third panic message: {s}\n", .{msg}) catch {};
7147 std.process.exit(0);
test/incremental/change_panic_handler_explicit created+141
......@@ -0,0 +1,141 @@
1#target=x86_64-linux-selfhosted
2#target=x86_64-linux-cbe
3#target=x86_64-windows-cbe
4#update=initial version
5#file=main.zig
6pub fn main() !u8 {
7 var a: u8 = undefined;
8 a = 255;
9 _ = a + 1;
10 return 1;
11}
12const no_panic = std.debug.no_panic;
13pub const panic = struct {
14 pub const call = myPanic;
15 pub fn integerOverflow() noreturn {
16 @panic("integer overflow");
17 }
18 pub const sentinelMismatch = no_panic.sentinelMismatch;
19 pub const unwrapError = no_panic.unwrapError;
20 pub const outOfBounds = no_panic.outOfBounds;
21 pub const startGreaterThanEnd = no_panic.startGreaterThanEnd;
22 pub const inactiveUnionField = no_panic.inactiveUnionField;
23 pub const reachedUnreachable = no_panic.reachedUnreachable;
24 pub const unwrapNull = no_panic.unwrapNull;
25 pub const castToNull = no_panic.castToNull;
26 pub const incorrectAlignment = no_panic.incorrectAlignment;
27 pub const invalidErrorCode = no_panic.invalidErrorCode;
28 pub const castTruncatedData = no_panic.castTruncatedData;
29 pub const negativeToUnsigned = no_panic.negativeToUnsigned;
30 pub const shlOverflow = no_panic.shlOverflow;
31 pub const shrOverflow = no_panic.shrOverflow;
32 pub const divideByZero = no_panic.divideByZero;
33 pub const exactDivisionRemainder = no_panic.exactDivisionRemainder;
34 pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds;
35 pub const corruptSwitch = no_panic.corruptSwitch;
36 pub const shiftRhsTooBig = no_panic.shiftRhsTooBig;
37 pub const invalidEnumValue = no_panic.invalidEnumValue;
38 pub const forLenMismatch = no_panic.forLenMismatch;
39 pub const memcpyLenMismatch = no_panic.memcpyLenMismatch;
40 pub const memcpyAlias = no_panic.memcpyAlias;
41 pub const noreturnReturned = no_panic.noreturnReturned;
42};
43fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
44 std.io.getStdOut().writer().print("panic message: {s}\n", .{msg}) catch {};
45 std.process.exit(0);
46}
47const std = @import("std");
48#expect_stdout="panic message: integer overflow\n"
49
50#update=change the panic handler body
51#file=main.zig
52pub fn main() !u8 {
53 var a: u8 = undefined;
54 a = 255;
55 _ = a + 1;
56 return 1;
57}
58const no_panic = std.debug.no_panic;
59pub const panic = struct {
60 pub const call = myPanic;
61 pub fn integerOverflow() noreturn {
62 @panic("integer overflow");
63 }
64 pub const sentinelMismatch = no_panic.sentinelMismatch;
65 pub const unwrapError = no_panic.unwrapError;
66 pub const outOfBounds = no_panic.outOfBounds;
67 pub const startGreaterThanEnd = no_panic.startGreaterThanEnd;
68 pub const inactiveUnionField = no_panic.inactiveUnionField;
69 pub const reachedUnreachable = no_panic.reachedUnreachable;
70 pub const unwrapNull = no_panic.unwrapNull;
71 pub const castToNull = no_panic.castToNull;
72 pub const incorrectAlignment = no_panic.incorrectAlignment;
73 pub const invalidErrorCode = no_panic.invalidErrorCode;
74 pub const castTruncatedData = no_panic.castTruncatedData;
75 pub const negativeToUnsigned = no_panic.negativeToUnsigned;
76 pub const shlOverflow = no_panic.shlOverflow;
77 pub const shrOverflow = no_panic.shrOverflow;
78 pub const divideByZero = no_panic.divideByZero;
79 pub const exactDivisionRemainder = no_panic.exactDivisionRemainder;
80 pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds;
81 pub const corruptSwitch = no_panic.corruptSwitch;
82 pub const shiftRhsTooBig = no_panic.shiftRhsTooBig;
83 pub const invalidEnumValue = no_panic.invalidEnumValue;
84 pub const forLenMismatch = no_panic.forLenMismatch;
85 pub const memcpyLenMismatch = no_panic.memcpyLenMismatch;
86 pub const memcpyAlias = no_panic.memcpyAlias;
87 pub const noreturnReturned = no_panic.noreturnReturned;
88};
89fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
90 std.io.getStdOut().writer().print("new panic message: {s}\n", .{msg}) catch {};
91 std.process.exit(0);
92}
93const std = @import("std");
94#expect_stdout="new panic message: integer overflow\n"
95
96#update=change the panic handler function value
97#file=main.zig
98pub fn main() !u8 {
99 var a: u8 = undefined;
100 a = 255;
101 _ = a + 1;
102 return 1;
103}
104const no_panic = std.debug.no_panic;
105pub const panic = struct {
106 pub const call = myPanicNew;
107 pub fn integerOverflow() noreturn {
108 @panic("integer overflow");
109 }
110 pub const sentinelMismatch = std.debug.no_panic.sentinelMismatch;
111 pub const unwrapError = std.debug.no_panic.unwrapError;
112 pub const outOfBounds = std.debug.no_panic.outOfBounds;
113 pub const startGreaterThanEnd = std.debug.no_panic.startGreaterThanEnd;
114 pub const inactiveUnionField = std.debug.no_panic.inactiveUnionField;
115 pub const messages = std.debug.no_panic.messages;
116 pub const reachedUnreachable = no_panic.reachedUnreachable;
117 pub const unwrapNull = no_panic.unwrapNull;
118 pub const castToNull = no_panic.castToNull;
119 pub const incorrectAlignment = no_panic.incorrectAlignment;
120 pub const invalidErrorCode = no_panic.invalidErrorCode;
121 pub const castTruncatedData = no_panic.castTruncatedData;
122 pub const negativeToUnsigned = no_panic.negativeToUnsigned;
123 pub const shlOverflow = no_panic.shlOverflow;
124 pub const shrOverflow = no_panic.shrOverflow;
125 pub const divideByZero = no_panic.divideByZero;
126 pub const exactDivisionRemainder = no_panic.exactDivisionRemainder;
127 pub const integerPartOutOfBounds = no_panic.integerPartOutOfBounds;
128 pub const corruptSwitch = no_panic.corruptSwitch;
129 pub const shiftRhsTooBig = no_panic.shiftRhsTooBig;
130 pub const invalidEnumValue = no_panic.invalidEnumValue;
131 pub const forLenMismatch = no_panic.forLenMismatch;
132 pub const memcpyLenMismatch = no_panic.memcpyLenMismatch;
133 pub const memcpyAlias = no_panic.memcpyAlias;
134 pub const noreturnReturned = no_panic.noreturnReturned;
135};
136fn myPanicNew(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn {
137 std.io.getStdOut().writer().print("third panic message: {s}\n", .{msg}) catch {};
138 std.process.exit(0);
139}
140const std = @import("std");
141#expect_stdout="third panic message: integer overflow\n"