| author | |
| committer | |
| log | 83991efe10d92c4b920d7b7fc75be98ed7854ad7 |
| tree | 7137ee5eb01517aede1c5503c29a2003fca71f80 |
| parent | b3d9b0e3f6bab5d662ec385cf754872f8a90607f |
| signature |
* `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 -> full20 files changed, 864 insertions(+), 482 deletions(-)
lib/std/Target.zig+1-1| ... | @@ -370,7 +370,7 @@ pub const Os = struct { | ... | @@ -370,7 +370,7 @@ pub const Os = struct { |
| 370 | range: std.SemanticVersion.Range, | 370 | range: std.SemanticVersion.Range, |
| 371 | glibc: std.SemanticVersion, | 371 | glibc: std.SemanticVersion, |
| 372 | /// Android API level. | 372 | /// Android API level. |
| 373 | android: u32 = 14, // This default value is to be deleted after zig1.wasm is updated. | 373 | android: u32, |
| 374 | 374 | ||
| 375 | pub inline fn includesVersion(range: LinuxVersionRange, ver: std.SemanticVersion) bool { | 375 | pub inline fn includesVersion(range: LinuxVersionRange, ver: std.SemanticVersion) bool { |
| 376 | return range.range.includesVersion(ver); | 376 | return range.range.includesVersion(ver); |
lib/std/builtin.zig+16-33| ... | @@ -1110,45 +1110,28 @@ pub const TestFn = struct { | ... | @@ -1110,45 +1110,28 @@ pub const TestFn = struct { |
| 1110 | /// Deprecated, use the `Panic` namespace instead. | 1110 | /// Deprecated, use the `Panic` namespace instead. |
| 1111 | /// To be deleted after 0.14.0 is released. | 1111 | /// To be deleted after 0.14.0 is released. |
| 1112 | pub const PanicFn = fn ([]const u8, ?*StackTrace, ?usize) noreturn; | 1112 | pub 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. | ||
| 1115 | pub const panic: PanicFn = Panic.call; | ||
| 1116 | 1113 | ||
| 1117 | /// This namespace is used by the Zig compiler to emit various kinds of safety | 1114 | /// 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 |
| 1119 | /// root source file. | 1116 | /// root source file. |
| 1120 | pub const Panic: type = if (@hasDecl(root, "Panic")) | 1117 | pub const panic: type = p: { |
| 1121 | root.Panic | 1118 | if (@hasDecl(root, "panic")) { |
| 1122 | else if (@hasDecl(root, "panic")) // Deprecated, use `Panic` instead. | 1119 | if (@TypeOf(root.panic) != type) { |
| 1123 | DeprecatedPanic | 1120 | break :p std.debug.FullPanic(root.panic); // Deprecated; make `panic` a namespace instead. |
| 1124 | else if (builtin.zig_backend == .stage2_riscv64) | 1121 | } |
| 1125 | std.debug.SimplePanic // https://github.com/ziglang/zig/issues/21519 | 1122 | break :p root.panic; |
| 1126 | else | 1123 | } |
| 1127 | std.debug.FormattedPanic; | 1124 | if (@hasDecl(root, "Panic")) { |
| 1128 | 1125 | break :p root.Panic; // Deprecated; use `panic` instead. | |
| 1129 | /// To be deleted after 0.14.0 is released. | 1126 | } |
| 1130 | const DeprecatedPanic = struct { | 1127 | if (builtin.zig_backend == .stage2_riscv64) { |
| 1131 | pub const call = root.panic; | 1128 | break :p std.debug.simple_panic; |
| 1132 | pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch; | 1129 | } |
| 1133 | pub const unwrapError = std.debug.FormattedPanic.unwrapError; | 1130 | break :p std.debug.FullPanic(std.debug.defaultPanic); |
| 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; | ||
| 1138 | }; | 1131 | }; |
| 1139 | 1132 | ||
| 1140 | /// To be deleted after zig1.wasm is updated. | 1133 | /// To be deleted after zig1.wasm is updated. |
| 1141 | pub const panicSentinelMismatch = Panic.sentinelMismatch; | 1134 | pub const Panic = panic; |
| 1142 | /// To be deleted after zig1.wasm is updated. | ||
| 1143 | pub const panicUnwrapError = Panic.unwrapError; | ||
| 1144 | /// To be deleted after zig1.wasm is updated. | ||
| 1145 | pub const panicOutOfBounds = Panic.outOfBounds; | ||
| 1146 | /// To be deleted after zig1.wasm is updated. | ||
| 1147 | pub const panicStartGreaterThanEnd = Panic.startGreaterThanEnd; | ||
| 1148 | /// To be deleted after zig1.wasm is updated. | ||
| 1149 | pub const panicInactiveUnionField = Panic.inactiveUnionField; | ||
| 1150 | /// To be deleted after zig1.wasm is updated. | ||
| 1151 | pub const panic_messages = Panic.messages; | ||
| 1152 | 1135 | ||
| 1153 | pub noinline fn returnError() void { | 1136 | pub noinline fn returnError() void { |
| 1154 | @branchHint(.unlikely); | 1137 | @branchHint(.unlikely); |
lib/std/debug.zig+119-4| ... | @@ -21,9 +21,124 @@ pub const SelfInfo = @import("debug/SelfInfo.zig"); | ... | @@ -21,9 +21,124 @@ pub const SelfInfo = @import("debug/SelfInfo.zig"); |
| 21 | pub const Info = @import("debug/Info.zig"); | 21 | pub const Info = @import("debug/Info.zig"); |
| 22 | pub const Coverage = @import("debug/Coverage.zig"); | 22 | pub const Coverage = @import("debug/Coverage.zig"); |
| 23 | 23 | ||
| 24 | pub const FormattedPanic = @import("debug/FormattedPanic.zig"); | 24 | pub const simple_panic = @import("debug/simple_panic.zig"); |
| 25 | pub const SimplePanic = @import("debug/SimplePanic.zig"); | 25 | pub const no_panic = @import("debug/no_panic.zig"); |
| 26 | pub const NoPanic = @import("debug/NoPanic.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`. | ||
| 30 | pub 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 | } | ||
| 27 | 142 | ||
| 28 | /// Unresolved source locations can be represented with a single `usize` that | 143 | /// Unresolved source locations can be represented with a single `usize` that |
| 29 | /// corresponds to a virtual memory address of the program counter. Combined | 144 | /// corresponds to a virtual memory address of the program counter. Combined |
| ... | @@ -441,7 +556,7 @@ pub fn panicExtra( | ... | @@ -441,7 +556,7 @@ pub fn panicExtra( |
| 441 | break :blk &buf; | 556 | break :blk &buf; |
| 442 | }, | 557 | }, |
| 443 | }; | 558 | }; |
| 444 | std.builtin.Panic.call(msg, trace, ret_addr); | 559 | std.builtin.panic.call(msg, trace, ret_addr); |
| 445 | } | 560 | } |
| 446 | 561 | ||
| 447 | /// Non-zero whenever the program triggered a panic. | 562 | /// 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 | |||
| 9 | const 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. | ||
| 14 | pub const call: fn ([]const u8, ?*std.builtin.StackTrace, ?usize) noreturn = std.debug.defaultPanic; | ||
| 15 | |||
| 16 | pub 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 | |||
| 23 | pub 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 | |||
| 28 | pub 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 | |||
| 33 | pub 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 | |||
| 38 | pub 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 | |||
| 45 | pub 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 | |||
| 6 | const std = @import("../std.zig"); | ||
| 7 | |||
| 8 | pub fn call(_: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { | ||
| 9 | @branchHint(.cold); | ||
| 10 | @trap(); | ||
| 11 | } | ||
| 12 | |||
| 13 | pub fn sentinelMismatch(_: anytype, _: anytype) noreturn { | ||
| 14 | @branchHint(.cold); | ||
| 15 | @trap(); | ||
| 16 | } | ||
| 17 | |||
| 18 | pub fn unwrapError(_: ?*std.builtin.StackTrace, _: anyerror) noreturn { | ||
| 19 | @branchHint(.cold); | ||
| 20 | @trap(); | ||
| 21 | } | ||
| 22 | |||
| 23 | pub fn outOfBounds(_: usize, _: usize) noreturn { | ||
| 24 | @branchHint(.cold); | ||
| 25 | @trap(); | ||
| 26 | } | ||
| 27 | |||
| 28 | pub fn startGreaterThanEnd(_: usize, _: usize) noreturn { | ||
| 29 | @branchHint(.cold); | ||
| 30 | @trap(); | ||
| 31 | } | ||
| 32 | |||
| 33 | pub fn inactiveUnionField(_: anytype, _: anytype) noreturn { | ||
| 34 | @branchHint(.cold); | ||
| 35 | @trap(); | ||
| 36 | } | ||
| 37 | |||
| 38 | pub 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 | |||
| 9 | const 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. | ||
| 14 | pub 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 | |||
| 24 | pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn { | ||
| 25 | _ = found; | ||
| 26 | call("sentinel mismatch", null, null); | ||
| 27 | } | ||
| 28 | |||
| 29 | pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn { | ||
| 30 | _ = ert; | ||
| 31 | _ = &err; | ||
| 32 | call("attempt to unwrap error", null, null); | ||
| 33 | } | ||
| 34 | |||
| 35 | pub fn outOfBounds(index: usize, len: usize) noreturn { | ||
| 36 | _ = index; | ||
| 37 | _ = len; | ||
| 38 | call("index out of bounds", null, null); | ||
| 39 | } | ||
| 40 | |||
| 41 | pub fn startGreaterThanEnd(start: usize, end: usize) noreturn { | ||
| 42 | _ = start; | ||
| 43 | _ = end; | ||
| 44 | call("start index is larger than end index", null, null); | ||
| 45 | } | ||
| 46 | |||
| 47 | pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn { | ||
| 48 | _ = accessed; | ||
| 49 | call("access of inactive union field", null, null); | ||
| 50 | } | ||
| 51 | |||
| 52 | pub 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 | |||
| 6 | const std = @import("../std.zig"); | ||
| 7 | |||
| 8 | pub fn call(_: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { | ||
| 9 | @branchHint(.cold); | ||
| 10 | @trap(); | ||
| 11 | } | ||
| 12 | |||
| 13 | pub fn sentinelMismatch(_: anytype, _: anytype) noreturn { | ||
| 14 | @branchHint(.cold); | ||
| 15 | @trap(); | ||
| 16 | } | ||
| 17 | |||
| 18 | pub fn unwrapError(_: ?*std.builtin.StackTrace, _: anyerror) noreturn { | ||
| 19 | @branchHint(.cold); | ||
| 20 | @trap(); | ||
| 21 | } | ||
| 22 | |||
| 23 | pub fn outOfBounds(_: usize, _: usize) noreturn { | ||
| 24 | @branchHint(.cold); | ||
| 25 | @trap(); | ||
| 26 | } | ||
| 27 | |||
| 28 | pub fn startGreaterThanEnd(_: usize, _: usize) noreturn { | ||
| 29 | @branchHint(.cold); | ||
| 30 | @trap(); | ||
| 31 | } | ||
| 32 | |||
| 33 | pub fn inactiveUnionField(_: anytype, _: anytype) noreturn { | ||
| 34 | @branchHint(.cold); | ||
| 35 | @trap(); | ||
| 36 | } | ||
| 37 | |||
| 38 | pub fn reachedUnreachable() noreturn { | ||
| 39 | @branchHint(.cold); | ||
| 40 | @trap(); | ||
| 41 | } | ||
| 42 | |||
| 43 | pub fn unwrapNull() noreturn { | ||
| 44 | @branchHint(.cold); | ||
| 45 | @trap(); | ||
| 46 | } | ||
| 47 | |||
| 48 | pub fn castToNull() noreturn { | ||
| 49 | @branchHint(.cold); | ||
| 50 | @trap(); | ||
| 51 | } | ||
| 52 | |||
| 53 | pub fn incorrectAlignment() noreturn { | ||
| 54 | @branchHint(.cold); | ||
| 55 | @trap(); | ||
| 56 | } | ||
| 57 | |||
| 58 | pub fn invalidErrorCode() noreturn { | ||
| 59 | @branchHint(.cold); | ||
| 60 | @trap(); | ||
| 61 | } | ||
| 62 | |||
| 63 | pub fn castTruncatedData() noreturn { | ||
| 64 | @branchHint(.cold); | ||
| 65 | @trap(); | ||
| 66 | } | ||
| 67 | |||
| 68 | pub fn negativeToUnsigned() noreturn { | ||
| 69 | @branchHint(.cold); | ||
| 70 | @trap(); | ||
| 71 | } | ||
| 72 | |||
| 73 | pub fn integerOverflow() noreturn { | ||
| 74 | @branchHint(.cold); | ||
| 75 | @trap(); | ||
| 76 | } | ||
| 77 | |||
| 78 | pub fn shlOverflow() noreturn { | ||
| 79 | @branchHint(.cold); | ||
| 80 | @trap(); | ||
| 81 | } | ||
| 82 | |||
| 83 | pub fn shrOverflow() noreturn { | ||
| 84 | @branchHint(.cold); | ||
| 85 | @trap(); | ||
| 86 | } | ||
| 87 | |||
| 88 | pub fn divideByZero() noreturn { | ||
| 89 | @branchHint(.cold); | ||
| 90 | @trap(); | ||
| 91 | } | ||
| 92 | |||
| 93 | pub fn exactDivisionRemainder() noreturn { | ||
| 94 | @branchHint(.cold); | ||
| 95 | @trap(); | ||
| 96 | } | ||
| 97 | |||
| 98 | pub fn integerPartOutOfBounds() noreturn { | ||
| 99 | @branchHint(.cold); | ||
| 100 | @trap(); | ||
| 101 | } | ||
| 102 | |||
| 103 | pub fn corruptSwitch() noreturn { | ||
| 104 | @branchHint(.cold); | ||
| 105 | @trap(); | ||
| 106 | } | ||
| 107 | |||
| 108 | pub fn shiftRhsTooBig() noreturn { | ||
| 109 | @branchHint(.cold); | ||
| 110 | @trap(); | ||
| 111 | } | ||
| 112 | |||
| 113 | pub fn invalidEnumValue() noreturn { | ||
| 114 | @branchHint(.cold); | ||
| 115 | @trap(); | ||
| 116 | } | ||
| 117 | |||
| 118 | pub fn forLenMismatch() noreturn { | ||
| 119 | @branchHint(.cold); | ||
| 120 | @trap(); | ||
| 121 | } | ||
| 122 | |||
| 123 | pub fn memcpyLenMismatch() noreturn { | ||
| 124 | @branchHint(.cold); | ||
| 125 | @trap(); | ||
| 126 | } | ||
| 127 | |||
| 128 | pub fn memcpyAlias() noreturn { | ||
| 129 | @branchHint(.cold); | ||
| 130 | @trap(); | ||
| 131 | } | ||
| 132 | |||
| 133 | pub fn noreturnReturned() noreturn { | ||
| 134 | @branchHint(.cold); | ||
| 135 | @trap(); | ||
| 136 | } | ||
| 137 | |||
| 138 | /// To be deleted after zig1.wasm update. | ||
| 139 | pub 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 | |||
| 9 | const 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. | ||
| 14 | pub 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 | |||
| 24 | pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn { | ||
| 25 | _ = found; | ||
| 26 | call("sentinel mismatch", null, null); | ||
| 27 | } | ||
| 28 | |||
| 29 | pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn { | ||
| 30 | _ = ert; | ||
| 31 | _ = &err; | ||
| 32 | call("attempt to unwrap error", null, null); | ||
| 33 | } | ||
| 34 | |||
| 35 | pub fn outOfBounds(index: usize, len: usize) noreturn { | ||
| 36 | _ = index; | ||
| 37 | _ = len; | ||
| 38 | call("index out of bounds", null, null); | ||
| 39 | } | ||
| 40 | |||
| 41 | pub fn startGreaterThanEnd(start: usize, end: usize) noreturn { | ||
| 42 | _ = start; | ||
| 43 | _ = end; | ||
| 44 | call("start index is larger than end index", null, null); | ||
| 45 | } | ||
| 46 | |||
| 47 | pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn { | ||
| 48 | _ = accessed; | ||
| 49 | call("access of inactive union field", null, null); | ||
| 50 | } | ||
| 51 | |||
| 52 | pub fn reachedUnreachable() noreturn { | ||
| 53 | call("reached unreachable code", null, null); | ||
| 54 | } | ||
| 55 | |||
| 56 | pub fn unwrapNull() noreturn { | ||
| 57 | call("attempt to use null value", null, null); | ||
| 58 | } | ||
| 59 | |||
| 60 | pub fn castToNull() noreturn { | ||
| 61 | call("cast causes pointer to be null", null, null); | ||
| 62 | } | ||
| 63 | |||
| 64 | pub fn incorrectAlignment() noreturn { | ||
| 65 | call("incorrect alignment", null, null); | ||
| 66 | } | ||
| 67 | |||
| 68 | pub fn invalidErrorCode() noreturn { | ||
| 69 | call("invalid error code", null, null); | ||
| 70 | } | ||
| 71 | |||
| 72 | pub fn castTruncatedData() noreturn { | ||
| 73 | call("integer cast truncated bits", null, null); | ||
| 74 | } | ||
| 75 | |||
| 76 | pub fn negativeToUnsigned() noreturn { | ||
| 77 | call("attempt to cast negative value to unsigned integer", null, null); | ||
| 78 | } | ||
| 79 | |||
| 80 | pub fn integerOverflow() noreturn { | ||
| 81 | call("integer overflow", null, null); | ||
| 82 | } | ||
| 83 | |||
| 84 | pub fn shlOverflow() noreturn { | ||
| 85 | call("left shift overflowed bits", null, null); | ||
| 86 | } | ||
| 87 | |||
| 88 | pub fn shrOverflow() noreturn { | ||
| 89 | call("right shift overflowed bits", null, null); | ||
| 90 | } | ||
| 91 | |||
| 92 | pub fn divideByZero() noreturn { | ||
| 93 | call("division by zero", null, null); | ||
| 94 | } | ||
| 95 | |||
| 96 | pub fn exactDivisionRemainder() noreturn { | ||
| 97 | call("exact division produced remainder", null, null); | ||
| 98 | } | ||
| 99 | |||
| 100 | pub fn integerPartOutOfBounds() noreturn { | ||
| 101 | call("integer part of floating point value out of bounds", null, null); | ||
| 102 | } | ||
| 103 | |||
| 104 | pub fn corruptSwitch() noreturn { | ||
| 105 | call("switch on corrupt value", null, null); | ||
| 106 | } | ||
| 107 | |||
| 108 | pub fn shiftRhsTooBig() noreturn { | ||
| 109 | call("shift amount is greater than the type size", null, null); | ||
| 110 | } | ||
| 111 | |||
| 112 | pub fn invalidEnumValue() noreturn { | ||
| 113 | call("invalid enum value", null, null); | ||
| 114 | } | ||
| 115 | |||
| 116 | pub fn forLenMismatch() noreturn { | ||
| 117 | call("for loop over objects with non-equal lengths", null, null); | ||
| 118 | } | ||
| 119 | |||
| 120 | pub fn memcpyLenMismatch() noreturn { | ||
| 121 | call("@memcpy arguments have non-equal lengths", null, null); | ||
| 122 | } | ||
| 123 | |||
| 124 | pub fn memcpyAlias() noreturn { | ||
| 125 | call("@memcpy arguments alias", null, null); | ||
| 126 | } | ||
| 127 | |||
| 128 | pub fn noreturnReturned() noreturn { | ||
| 129 | call("'noreturn' function returned", null, null); | ||
| 130 | } | ||
| 131 | |||
| 132 | /// To be deleted after zig1.wasm update. | ||
| 133 | pub 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 { | ... | @@ -448,8 +448,7 @@ pub fn fieldNames(comptime T: type) *const [fields(T).len][:0]const u8 { |
| 448 | return comptime blk: { | 448 | return comptime blk: { |
| 449 | const fieldInfos = fields(T); | 449 | const fieldInfos = fields(T); |
| 450 | var names: [fieldInfos.len][:0]const u8 = undefined; | 450 | var names: [fieldInfos.len][:0]const u8 = undefined; |
| 451 | // This concat can be removed with the next zig1 update. | 451 | for (&names, fieldInfos) |*name, field| name.* = field.name; |
| 452 | for (&names, fieldInfos) |*name, field| name.* = field.name ++ ""; | ||
| 453 | const final = names; | 452 | const final = names; |
| 454 | break :blk &final; | 453 | break :blk &final; |
| 455 | }; | 454 | }; |
src/Sema.zig+89-66| ... | @@ -5918,13 +5918,14 @@ fn zirCompileLog( | ... | @@ -5918,13 +5918,14 @@ fn zirCompileLog( |
| 5918 | } | 5918 | } |
| 5919 | 5919 | ||
| 5920 | fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | 5920 | fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| 5921 | const pt = sema.pt; | ||
| 5922 | const zcu = pt.zcu; | ||
| 5923 | |||
| 5921 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; | 5924 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 5922 | const src = block.nodeOffset(inst_data.src_node); | 5925 | const src = block.nodeOffset(inst_data.src_node); |
| 5923 | const msg_inst = try sema.resolveInst(inst_data.operand); | 5926 | const msg_inst = try sema.resolveInst(inst_data.operand); |
| 5924 | 5927 | ||
| 5925 | // `panicWithMsg` would perform this coercion for us, but we can get a better | 5928 | const coerced_msg = try sema.coerce(block, .slice_const_u8, msg_inst, block.builtinCallArgSrc(inst_data.src_node, 0)); |
| 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 | 5929 | ||
| 5929 | if (block.isComptime()) { | 5930 | if (block.isComptime()) { |
| 5930 | return sema.fail(block, src, "encountered @panic at comptime", .{}); | 5931 | 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 | ... | @@ -5936,7 +5937,23 @@ fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 5936 | sema.branch_hint = .cold; | 5937 | sema.branch_hint = .cold; |
| 5937 | } | 5938 | } |
| 5938 | 5939 | ||
| 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"); | ||
| 5940 | } | 5957 | } |
| 5941 | 5958 | ||
| 5942 | fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | 5959 | fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| ... | @@ -13787,7 +13804,7 @@ fn maybeErrorUnwrap( | ... | @@ -13787,7 +13804,7 @@ fn maybeErrorUnwrap( |
| 13787 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; | 13804 | const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node; |
| 13788 | const msg_inst = try sema.resolveInst(inst_data.operand); | 13805 | const msg_inst = try sema.resolveInst(inst_data.operand); |
| 13789 | 13806 | ||
| 13790 | const panic_fn = try getBuiltin(sema, operand_src, .@"Panic.call"); | 13807 | const panic_fn = try getBuiltin(sema, operand_src, .@"panic.call"); |
| 13791 | const err_return_trace = try sema.getErrorReturnTrace(block); | 13808 | const err_return_trace = try sema.getErrorReturnTrace(block); |
| 13792 | const args: [3]Air.Inst.Ref = .{ msg_inst, err_return_trace, .null_value }; | 13809 | const args: [3]Air.Inst.Ref = .{ msg_inst, err_return_trace, .null_value }; |
| 13793 | try sema.callBuiltin(block, operand_src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check"); | 13810 | try sema.callBuiltin(block, operand_src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check"); |
| ... | @@ -27083,15 +27100,16 @@ fn explainWhyTypeIsNotPacked( | ... | @@ -27083,15 +27100,16 @@ fn explainWhyTypeIsNotPacked( |
| 27083 | /// Backends depend on panic decls being available when lowering safety-checked | 27100 | /// Backends depend on panic decls being available when lowering safety-checked |
| 27084 | /// instructions. This function ensures the panic function will be available to | 27101 | /// instructions. This function ensures the panic function will be available to |
| 27085 | /// be called during that time. | 27102 | /// be called during that time. |
| 27086 | fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.PanicId) !InternPool.Index { | 27103 | fn preparePanicId(sema: *Sema, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) !InternPool.Index { |
| 27087 | const zcu = sema.pt.zcu; | 27104 | const zcu = sema.pt.zcu; |
| 27088 | try sema.ensureMemoizedStateResolved(src, .panic); | 27105 | 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); | ||
| 27090 | switch (sema.owner.unwrap()) { | 27108 | switch (sema.owner.unwrap()) { |
| 27091 | .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {}, | 27109 | .@"comptime", .nav_ty, .nav_val, .type, .memoized_state => {}, |
| 27092 | .func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(owner_func, true), | 27110 | .func => |owner_func| zcu.intern_pool.funcSetHasErrorTrace(owner_func, true), |
| 27093 | } | 27111 | } |
| 27094 | return zcu.builtin_decl_values.get(panic_id.toBuiltin()); | 27112 | return panic_func; |
| 27095 | } | 27113 | } |
| 27096 | 27114 | ||
| 27097 | fn addSafetyCheck( | 27115 | fn addSafetyCheck( |
| ... | @@ -27099,7 +27117,7 @@ fn addSafetyCheck( | ... | @@ -27099,7 +27117,7 @@ fn addSafetyCheck( |
| 27099 | parent_block: *Block, | 27117 | parent_block: *Block, |
| 27100 | src: LazySrcLoc, | 27118 | src: LazySrcLoc, |
| 27101 | ok: Air.Inst.Ref, | 27119 | ok: Air.Inst.Ref, |
| 27102 | panic_id: Zcu.PanicId, | 27120 | panic_id: Zcu.SimplePanicId, |
| 27103 | ) !void { | 27121 | ) !void { |
| 27104 | const gpa = sema.gpa; | 27122 | const gpa = sema.gpa; |
| 27105 | assert(!parent_block.isComptime()); | 27123 | assert(!parent_block.isComptime()); |
| ... | @@ -27186,29 +27204,6 @@ fn addSafetyCheckExtra( | ... | @@ -27186,29 +27204,6 @@ fn addSafetyCheckExtra( |
| 27186 | parent_block.instructions.appendAssumeCapacity(block_inst); | 27204 | parent_block.instructions.appendAssumeCapacity(block_inst); |
| 27187 | } | 27205 | } |
| 27188 | 27206 | ||
| 27189 | fn 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 | |||
| 27212 | fn addSafetyCheckUnwrapError( | 27207 | fn addSafetyCheckUnwrapError( |
| 27213 | sema: *Sema, | 27208 | sema: *Sema, |
| 27214 | parent_block: *Block, | 27209 | parent_block: *Block, |
| ... | @@ -27246,7 +27241,7 @@ fn safetyPanicUnwrapError(sema: *Sema, block: *Block, src: LazySrcLoc, err: Air. | ... | @@ -27246,7 +27241,7 @@ fn safetyPanicUnwrapError(sema: *Sema, block: *Block, src: LazySrcLoc, err: Air. |
| 27246 | if (!zcu.backendSupportsFeature(.panic_fn)) { | 27241 | if (!zcu.backendSupportsFeature(.panic_fn)) { |
| 27247 | _ = try block.addNoOp(.trap); | 27242 | _ = try block.addNoOp(.trap); |
| 27248 | } else { | 27243 | } else { |
| 27249 | const panic_fn = try getBuiltin(sema, src, .@"Panic.unwrapError"); | 27244 | const panic_fn = try getBuiltin(sema, src, .@"panic.unwrapError"); |
| 27250 | const err_return_trace = try sema.getErrorReturnTrace(block); | 27245 | const err_return_trace = try sema.getErrorReturnTrace(block); |
| 27251 | const args: [2]Air.Inst.Ref = .{ err_return_trace, err }; | 27246 | const args: [2]Air.Inst.Ref = .{ err_return_trace, err }; |
| 27252 | try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check"); | 27247 | try sema.callBuiltin(block, src, Air.internedToRef(panic_fn), .auto, &args, .@"safety check"); |
| ... | @@ -27263,7 +27258,7 @@ fn addSafetyCheckIndexOob( | ... | @@ -27263,7 +27258,7 @@ fn addSafetyCheckIndexOob( |
| 27263 | ) !void { | 27258 | ) !void { |
| 27264 | assert(!parent_block.isComptime()); | 27259 | assert(!parent_block.isComptime()); |
| 27265 | const ok = try parent_block.addBinOp(cmp_op, index, len); | 27260 | 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 }); |
| 27267 | } | 27262 | } |
| 27268 | 27263 | ||
| 27269 | fn addSafetyCheckInactiveUnionField( | 27264 | fn addSafetyCheckInactiveUnionField( |
| ... | @@ -27275,7 +27270,7 @@ fn addSafetyCheckInactiveUnionField( | ... | @@ -27275,7 +27270,7 @@ fn addSafetyCheckInactiveUnionField( |
| 27275 | ) !void { | 27270 | ) !void { |
| 27276 | assert(!parent_block.isComptime()); | 27271 | assert(!parent_block.isComptime()); |
| 27277 | const ok = try parent_block.addBinOp(.cmp_eq, active_tag, wanted_tag); | 27272 | 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 }); |
| 27279 | } | 27274 | } |
| 27280 | 27275 | ||
| 27281 | fn addSafetyCheckSentinelMismatch( | 27276 | fn addSafetyCheckSentinelMismatch( |
| ... | @@ -27316,7 +27311,7 @@ fn addSafetyCheckSentinelMismatch( | ... | @@ -27316,7 +27311,7 @@ fn addSafetyCheckSentinelMismatch( |
| 27316 | break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel); | 27311 | break :ok try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel); |
| 27317 | }; | 27312 | }; |
| 27318 | 27313 | ||
| 27319 | return addSafetyCheckCall(sema, parent_block, src, ok, .@"Panic.sentinelMismatch", &.{ | 27314 | return addSafetyCheckCall(sema, parent_block, src, ok, .@"panic.sentinelMismatch", &.{ |
| 27320 | expected_sentinel, actual_sentinel, | 27315 | expected_sentinel, actual_sentinel, |
| 27321 | }); | 27316 | }); |
| 27322 | } | 27317 | } |
| ... | @@ -27358,9 +27353,13 @@ fn addSafetyCheckCall( | ... | @@ -27358,9 +27353,13 @@ fn addSafetyCheckCall( |
| 27358 | } | 27353 | } |
| 27359 | 27354 | ||
| 27360 | /// This does not set `sema.branch_hint`. | 27355 | /// This does not set `sema.branch_hint`. |
| 27361 | fn safetyPanic(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.PanicId) CompileError!void { | 27356 | fn safetyPanic(sema: *Sema, block: *Block, src: LazySrcLoc, panic_id: Zcu.SimplePanicId) CompileError!void { |
| 27362 | const msg_val = try sema.preparePanicId(src, panic_id); | 27357 | if (!sema.pt.zcu.backendSupportsFeature(.panic_fn)) { |
| 27363 | try sema.panicWithMsg(block, src, Air.internedToRef(msg_val), .@"safety check"); | 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 | } | ||
| 27364 | } | 27363 | } |
| 27365 | 27364 | ||
| 27366 | fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void { | 27365 | fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void { |
| ... | @@ -32818,7 +32817,7 @@ fn analyzeSlice( | ... | @@ -32818,7 +32817,7 @@ fn analyzeSlice( |
| 32818 | assert(!block.isComptime()); | 32817 | assert(!block.isComptime()); |
| 32819 | try sema.requireRuntimeBlock(block, src, runtime_src.?); | 32818 | try sema.requireRuntimeBlock(block, src, runtime_src.?); |
| 32820 | const ok = try block.addBinOp(.cmp_lte, start, end); | 32819 | 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 }); |
| 32822 | } | 32821 | } |
| 32823 | const new_len = if (by_length) | 32822 | const new_len = if (by_length) |
| 32824 | try sema.coerce(block, Type.usize, uncasted_end_opt, end_src) | 32823 | 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, | ... | @@ -38525,14 +38524,9 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, |
| 38525 | break :val uncoerced_val; | 38524 | break :val uncoerced_val; |
| 38526 | }, | 38525 | }, |
| 38527 | .func => val: { | 38526 | .func => val: { |
| 38528 | if (try sema.getExpectedBuiltinFnType(src, builtin_decl)) |func_ty| { | 38527 | const func_ty = try sema.getExpectedBuiltinFnType(src, builtin_decl); |
| 38529 | const coerced = try sema.coerce(block, func_ty, Air.internedToRef(uncoerced_val.toIntern()), src); | 38528 | const coerced = try sema.coerce(block, func_ty, Air.internedToRef(uncoerced_val.toIntern()), src); |
| 38530 | break :val .fromInterned(coerced.toInterned().?); | 38529 | 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; | ||
| 38536 | }, | 38530 | }, |
| 38537 | .string => val: { | 38531 | .string => val: { |
| 38538 | const coerced = try sema.coerce(block, .slice_const_u8, Air.internedToRef(uncoerced_val.toIntern()), src); | 38532 | 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, | ... | @@ -38567,16 +38561,19 @@ pub fn analyzeMemoizedState(sema: *Sema, block: *Block, simple_src: LazySrcLoc, |
| 38567 | return any_changed; | 38561 | return any_changed; |
| 38568 | } | 38562 | } |
| 38569 | 38563 | ||
| 38570 | /// Given that `decl.kind() == .func`, get the type expected of the function if necessary. | 38564 | /// Given that `decl.kind() == .func`, get the type expected of the function. |
| 38571 | /// If this will be type checked by `Sema` anyway, this function may return `null`. In | 38565 | fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) CompileError!Type { |
| 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. | ||
| 38575 | fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) CompileError!?Type { | ||
| 38576 | const pt = sema.pt; | 38566 | const pt = sema.pt; |
| 38577 | return switch (decl) { | 38567 | 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 | |||
| 38578 | // `fn ([]const u8, ?*StackTrace, ?usize) noreturn` | 38575 | // `fn ([]const u8, ?*StackTrace, ?usize) noreturn` |
| 38579 | .@"Panic.call" => try pt.funcType(.{ | 38576 | .@"panic.call" => try pt.funcType(.{ |
| 38580 | .param_types = &.{ | 38577 | .param_types = &.{ |
| 38581 | .slice_const_u8_type, | 38578 | .slice_const_u8_type, |
| 38582 | (try pt.optionalType( | 38579 | (try pt.optionalType( |
| ... | @@ -38589,8 +38586,17 @@ fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) | ... | @@ -38589,8 +38586,17 @@ fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) |
| 38589 | .return_type = .noreturn_type, | 38586 | .return_type = .noreturn_type, |
| 38590 | }), | 38587 | }), |
| 38591 | 38588 | ||
| 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 | |||
| 38592 | // `fn (?*StackTrace, anyerror) noreturn` | 38598 | // `fn (?*StackTrace, anyerror) noreturn` |
| 38593 | .@"Panic.unwrapError" => try pt.funcType(.{ | 38599 | .@"panic.unwrapError" => try pt.funcType(.{ |
| 38594 | .param_types = &.{ | 38600 | .param_types = &.{ |
| 38595 | (try pt.optionalType( | 38601 | (try pt.optionalType( |
| 38596 | (try pt.singleMutPtrType( | 38602 | (try pt.singleMutPtrType( |
| ... | @@ -38603,21 +38609,38 @@ fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) | ... | @@ -38603,21 +38609,38 @@ fn getExpectedBuiltinFnType(sema: *Sema, src: LazySrcLoc, decl: Zcu.BuiltinDecl) |
| 38603 | }), | 38609 | }), |
| 38604 | 38610 | ||
| 38605 | // `fn (usize, usize) noreturn` | 38611 | // `fn (usize, usize) noreturn` |
| 38606 | .@"Panic.outOfBounds", | 38612 | .@"panic.outOfBounds", |
| 38607 | .@"Panic.startGreaterThanEnd", | 38613 | .@"panic.startGreaterThanEnd", |
| 38608 | => try pt.funcType(.{ | 38614 | => try pt.funcType(.{ |
| 38609 | .param_types = &.{ .usize_type, .usize_type }, | 38615 | .param_types = &.{ .usize_type, .usize_type }, |
| 38610 | .return_type = .noreturn_type, | 38616 | .return_type = .noreturn_type, |
| 38611 | }), | 38617 | }), |
| 38612 | 38618 | ||
| 38613 | // Generic functions, so calls are necessarily validated by Sema | 38619 | // `fn () noreturn` |
| 38614 | .@"Panic.sentinelMismatch", | 38620 | .@"panic.reachedUnreachable", |
| 38615 | .@"Panic.inactiveUnionField", | 38621 | .@"panic.unwrapNull", |
| 38616 | => null, | 38622 | .@"panic.castToNull", |
| 38617 | 38623 | .@"panic.incorrectAlignment", | |
| 38618 | // Other functions called exclusively by Sema | 38624 | .@"panic.invalidErrorCode", |
| 38619 | .returnError, | 38625 | .@"panic.castTruncatedData", |
| 38620 | => null, | 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 | }), | ||
| 38621 | 38644 | ||
| 38622 | else => unreachable, | 38645 | else => unreachable, |
| 38623 | }; | 38646 | }; |
src/Zcu.zig+81-74| ... | @@ -269,34 +269,33 @@ pub const BuiltinDecl = enum { | ... | @@ -269,34 +269,33 @@ pub const BuiltinDecl = enum { |
| 269 | @"Type.Opaque", | 269 | @"Type.Opaque", |
| 270 | @"Type.Declaration", | 270 | @"Type.Declaration", |
| 271 | 271 | ||
| 272 | Panic, | 272 | panic, |
| 273 | @"Panic.call", | 273 | @"panic.call", |
| 274 | @"Panic.sentinelMismatch", | 274 | @"panic.sentinelMismatch", |
| 275 | @"Panic.unwrapError", | 275 | @"panic.unwrapError", |
| 276 | @"Panic.outOfBounds", | 276 | @"panic.outOfBounds", |
| 277 | @"Panic.startGreaterThanEnd", | 277 | @"panic.startGreaterThanEnd", |
| 278 | @"Panic.inactiveUnionField", | 278 | @"panic.inactiveUnionField", |
| 279 | @"Panic.messages", | 279 | @"panic.reachedUnreachable", |
| 280 | @"Panic.messages.reached_unreachable", | 280 | @"panic.unwrapNull", |
| 281 | @"Panic.messages.unwrap_null", | 281 | @"panic.castToNull", |
| 282 | @"Panic.messages.cast_to_null", | 282 | @"panic.incorrectAlignment", |
| 283 | @"Panic.messages.incorrect_alignment", | 283 | @"panic.invalidErrorCode", |
| 284 | @"Panic.messages.invalid_error_code", | 284 | @"panic.castTruncatedData", |
| 285 | @"Panic.messages.cast_truncated_data", | 285 | @"panic.negativeToUnsigned", |
| 286 | @"Panic.messages.negative_to_unsigned", | 286 | @"panic.integerOverflow", |
| 287 | @"Panic.messages.integer_overflow", | 287 | @"panic.shlOverflow", |
| 288 | @"Panic.messages.shl_overflow", | 288 | @"panic.shrOverflow", |
| 289 | @"Panic.messages.shr_overflow", | 289 | @"panic.divideByZero", |
| 290 | @"Panic.messages.divide_by_zero", | 290 | @"panic.exactDivisionRemainder", |
| 291 | @"Panic.messages.exact_division_remainder", | 291 | @"panic.integerPartOutOfBounds", |
| 292 | @"Panic.messages.integer_part_out_of_bounds", | 292 | @"panic.corruptSwitch", |
| 293 | @"Panic.messages.corrupt_switch", | 293 | @"panic.shiftRhsTooBig", |
| 294 | @"Panic.messages.shift_rhs_too_big", | 294 | @"panic.invalidEnumValue", |
| 295 | @"Panic.messages.invalid_enum_value", | 295 | @"panic.forLenMismatch", |
| 296 | @"Panic.messages.for_len_mismatch", | 296 | @"panic.memcpyLenMismatch", |
| 297 | @"Panic.messages.memcpy_len_mismatch", | 297 | @"panic.memcpyAlias", |
| 298 | @"Panic.messages.memcpy_alias", | 298 | @"panic.noreturnReturned", |
| 299 | @"Panic.messages.noreturn_returned", | ||
| 300 | 299 | ||
| 301 | VaList, | 300 | VaList, |
| 302 | 301 | ||
| ... | @@ -345,39 +344,35 @@ pub const BuiltinDecl = enum { | ... | @@ -345,39 +344,35 @@ pub const BuiltinDecl = enum { |
| 345 | .@"Type.Declaration", | 344 | .@"Type.Declaration", |
| 346 | => .type, | 345 | => .type, |
| 347 | 346 | ||
| 348 | .Panic => .type, | 347 | .panic => .type, |
| 349 | 348 | ||
| 350 | .@"Panic.call", | 349 | .@"panic.call", |
| 351 | .@"Panic.sentinelMismatch", | 350 | .@"panic.sentinelMismatch", |
| 352 | .@"Panic.unwrapError", | 351 | .@"panic.unwrapError", |
| 353 | .@"Panic.outOfBounds", | 352 | .@"panic.outOfBounds", |
| 354 | .@"Panic.startGreaterThanEnd", | 353 | .@"panic.startGreaterThanEnd", |
| 355 | .@"Panic.inactiveUnionField", | 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", | ||
| 356 | => .func, | 375 | => .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, | ||
| 381 | }; | 376 | }; |
| 382 | } | 377 | } |
| 383 | 378 | ||
| ... | @@ -423,7 +418,7 @@ pub const BuiltinDecl = enum { | ... | @@ -423,7 +418,7 @@ pub const BuiltinDecl = enum { |
| 423 | const Memoized = std.enums.EnumArray(BuiltinDecl, InternPool.Index); | 418 | const Memoized = std.enums.EnumArray(BuiltinDecl, InternPool.Index); |
| 424 | }; | 419 | }; |
| 425 | 420 | ||
| 426 | pub const PanicId = enum { | 421 | pub const SimplePanicId = enum { |
| 427 | reached_unreachable, | 422 | reached_unreachable, |
| 428 | unwrap_null, | 423 | unwrap_null, |
| 429 | cast_to_null, | 424 | cast_to_null, |
| ... | @@ -445,19 +440,31 @@ pub const PanicId = enum { | ... | @@ -445,19 +440,31 @@ pub const PanicId = enum { |
| 445 | memcpy_alias, | 440 | memcpy_alias, |
| 446 | noreturn_returned, | 441 | noreturn_returned, |
| 447 | 442 | ||
| 448 | pub fn toBuiltin(id: PanicId) BuiltinDecl { | 443 | pub fn toBuiltin(id: SimplePanicId) BuiltinDecl { |
| 449 | const first_msg: PanicId = @enumFromInt(0); | 444 | return switch (id) { |
| 450 | const first_decl = @field(BuiltinDecl, "Panic.messages." ++ @tagName(first_msg)); | 445 | // zig fmt: off |
| 451 | comptime { | 446 | .reached_unreachable => .@"panic.reachedUnreachable", |
| 452 | // Ensure that the messages are ordered the same in `BuiltinDecl` as they are here. | 447 | .unwrap_null => .@"panic.unwrapNull", |
| 453 | for (@typeInfo(PanicId).@"enum".fields) |panic_field| { | 448 | .cast_to_null => .@"panic.castToNull", |
| 454 | const expect_name = "Panic.messages." ++ panic_field.name; | 449 | .incorrect_alignment => .@"panic.incorrectAlignment", |
| 455 | const expect_idx = @intFromEnum(first_decl) + panic_field.value; | 450 | .invalid_error_code => .@"panic.invalidErrorCode", |
| 456 | const actual_idx = @intFromEnum(@field(BuiltinDecl, expect_name)); | 451 | .cast_truncated_data => .@"panic.castTruncatedData", |
| 457 | assert(expect_idx == actual_idx); | 452 | .negative_to_unsigned => .@"panic.negativeToUnsigned", |
| 458 | } | 453 | .integer_overflow => .@"panic.integerOverflow", |
| 459 | } | 454 | .shl_overflow => .@"panic.shlOverflow", |
| 460 | return @enumFromInt(@intFromEnum(first_decl) + @intFromEnum(id)); | 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 | }; | ||
| 461 | } | 468 | } |
| 462 | }; | 469 | }; |
| 463 | 470 |
src/Zcu/PerThread.zig+1-1| ... | @@ -605,7 +605,7 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized | ... | @@ -605,7 +605,7 @@ pub fn ensureMemoizedStateUpToDate(pt: Zcu.PerThread, stage: InternPool.Memoized |
| 605 | // We use an arbitrary element to check if the state has been resolved yet. | 605 | // We use an arbitrary element to check if the state has been resolved yet. |
| 606 | const to_check: Zcu.BuiltinDecl = switch (stage) { | 606 | const to_check: Zcu.BuiltinDecl = switch (stage) { |
| 607 | .main => .Type, | 607 | .main => .Type, |
| 608 | .panic => .Panic, | 608 | .panic => .panic, |
| 609 | .va_list => .VaList, | 609 | .va_list => .VaList, |
| 610 | }; | 610 | }; |
| 611 | if (zcu.builtin_decl_values.get(to_check) != .none) return; | 611 | if (zcu.builtin_decl_values.get(to_check) != .none) return; |
src/codegen/llvm.zig+5-44| ... | @@ -5019,18 +5019,6 @@ pub const FuncGen = struct { | ... | @@ -5019,18 +5019,6 @@ pub const FuncGen = struct { |
| 5019 | ); | 5019 | ); |
| 5020 | } | 5020 | } |
| 5021 | 5021 | ||
| 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 | |||
| 5034 | fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air.CoveragePoint) Error!void { | 5022 | fn genBody(self: *FuncGen, body: []const Air.Inst.Index, coverage_point: Air.CoveragePoint) Error!void { |
| 5035 | const o = self.ng.object; | 5023 | const o = self.ng.object; |
| 5036 | const zcu = o.pt.zcu; | 5024 | const zcu = o.pt.zcu; |
| ... | @@ -5732,30 +5720,14 @@ pub const FuncGen = struct { | ... | @@ -5732,30 +5720,14 @@ pub const FuncGen = struct { |
| 5732 | } | 5720 | } |
| 5733 | } | 5721 | } |
| 5734 | 5722 | ||
| 5735 | fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.PanicId) !void { | 5723 | fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) !void { |
| 5736 | const o = fg.ng.object; | 5724 | const o = fg.ng.object; |
| 5737 | const zcu = o.pt.zcu; | 5725 | 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(); | ||
| 5746 | const target = zcu.getTarget(); | 5726 | const target = zcu.getTarget(); |
| 5747 | const llvm_usize = try o.lowerType(Type.usize); | 5727 | const panic_func = zcu.funcInfo(zcu.builtin_decl_values.get(panic_id.toBuiltin())); |
| 5748 | // example: | 5728 | const fn_info = zcu.typeToFunc(.fromInterned(panic_func.ty)).?; |
| 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))).?; | ||
| 5758 | const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav); | 5729 | const panic_global = try o.resolveLlvmFunction(panic_func.owner_nav); |
| 5730 | |||
| 5759 | const has_err_trace = zcu.comp.config.any_error_tracing and fn_info.cc == .auto; | 5731 | const has_err_trace = zcu.comp.config.any_error_tracing and fn_info.cc == .auto; |
| 5760 | if (has_err_trace) assert(fg.err_ret_trace != .none); | 5732 | if (has_err_trace) assert(fg.err_ret_trace != .none); |
| 5761 | _ = try fg.wip.callIntrinsicAssumeCold(); | 5733 | _ = try fg.wip.callIntrinsicAssumeCold(); |
| ... | @@ -5765,18 +5737,7 @@ pub const FuncGen = struct { | ... | @@ -5765,18 +5737,7 @@ pub const FuncGen = struct { |
| 5765 | .none, | 5737 | .none, |
| 5766 | panic_global.typeOf(&o.builder), | 5738 | panic_global.typeOf(&o.builder), |
| 5767 | panic_global.toValue(&o.builder), | 5739 | panic_global.toValue(&o.builder), |
| 5768 | if (has_err_trace) &.{ | 5740 | if (has_err_trace) &.{fg.err_ret_trace} else &.{}, |
| 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 | }, | ||
| 5780 | "", | 5741 | "", |
| 5781 | ); | 5742 | ); |
| 5782 | _ = try fg.wip.@"unreachable"(); | 5743 | _ = try fg.wip.@"unreachable"(); |
src/crash_report.zig+5-11| ... | @@ -18,18 +18,12 @@ const dev = @import("dev.zig"); | ... | @@ -18,18 +18,12 @@ const dev = @import("dev.zig"); |
| 18 | /// To use these crash report diagnostics, publish this panic in your main file | 18 | /// To use these crash report diagnostics, publish this panic in your main file |
| 19 | /// and add `pub const enable_segfault_handler = false;` to your `std_options`. | 19 | /// and add `pub const enable_segfault_handler = false;` to your `std_options`. |
| 20 | /// You will also need to call initialize() on startup, preferably as the very first operation in your program. | 20 | /// You will also need to call initialize() on startup, preferably as the very first operation in your program. |
| 21 | pub const Panic = if (build_options.enable_debug_extensions) struct { | 21 | pub const panic = if (build_options.enable_debug_extensions) |
| 22 | pub const call = compilerPanic; | 22 | std.debug.FullPanic(compilerPanic) |
| 23 | pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch; | 23 | else if (dev.env == .bootstrap) |
| 24 | pub const unwrapError = std.debug.FormattedPanic.unwrapError; | 24 | std.debug.simple_panic |
| 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 | ||
| 31 | else | 25 | else |
| 32 | std.debug.FormattedPanic; | 26 | std.debug.FullPanic(std.debug.defaultPanic); |
| 33 | 27 | ||
| 34 | /// Install signal handlers to identify crashes and report diagnostics. | 28 | /// Install signal handlers to identify crashes and report diagnostics. |
| 35 | pub fn initialize() void { | 29 | pub fn initialize() void { |
src/main.zig+1-1| ... | @@ -56,7 +56,7 @@ pub const std_options: std.Options = .{ | ... | @@ -56,7 +56,7 @@ pub const std_options: std.Options = .{ |
| 56 | }, | 56 | }, |
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | pub const Panic = crash_report.Panic; | 59 | pub const panic = crash_report.panic; |
| 60 | 60 | ||
| 61 | var wasi_preopens: fs.wasi.Preopens = undefined; | 61 | var wasi_preopens: fs.wasi.Preopens = undefined; |
| 62 | pub fn wasi_cwd() std.os.wasi.fd_t { | 62 | pub fn wasi_cwd() std.os.wasi.fd_t { |
test/cases/compile_errors/bad_panic_call_signature.zig created+46| ... | @@ -0,0 +1,46 @@ | ||
| 1 | const simple_panic = std.debug.simple_panic; | ||
| 2 | pub 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 | |||
| 36 | export fn foo(a: u8) void { | ||
| 37 | @setRuntimeSafety(true); | ||
| 38 | _ = a + 1; // safety check to reference the panic handler | ||
| 39 | } | ||
| 40 | |||
| 41 | const 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 @@ | ||
| 1 | const simple_panic = std.debug.simple_panic; | ||
| 2 | pub 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 | |||
| 31 | export fn foo(arr: *const [2]u8) void { | ||
| 32 | @setRuntimeSafety(true); | ||
| 33 | _ = arr[0..1 :0]; | ||
| 34 | } | ||
| 35 | |||
| 36 | const 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 @@ | ||
| 1 | pub 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 | |||
| 11 | fn badPanicSignature(msg: []const u8, bad1: usize, bad2: void) noreturn { | ||
| 12 | _ = msg; | ||
| 13 | _ = bad1; | ||
| 14 | _ = bad2; | ||
| 15 | @trap(); | ||
| 16 | } | ||
| 17 | |||
| 18 | export fn foo(a: u8) void { | ||
| 19 | @setRuntimeSafety(true); | ||
| 20 | _ = a + 1; // safety check to reference the panic handler | ||
| 21 | } | ||
| 22 | |||
| 23 | const 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 { | ... | @@ -9,15 +9,7 @@ pub fn main() !u8 { |
| 9 | _ = a + 1; | 9 | _ = a + 1; |
| 10 | return 1; | 10 | return 1; |
| 11 | } | 11 | } |
| 12 | pub const Panic = struct { | 12 | pub const panic = std.debug.FullPanic(myPanic); |
| 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 | }; | ||
| 21 | fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { | 13 | fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { |
| 22 | std.io.getStdOut().writer().print("panic message: {s}\n", .{msg}) catch {}; | 14 | std.io.getStdOut().writer().print("panic message: {s}\n", .{msg}) catch {}; |
| 23 | std.process.exit(0); | 15 | std.process.exit(0); |
| ... | @@ -33,15 +25,7 @@ pub fn main() !u8 { | ... | @@ -33,15 +25,7 @@ pub fn main() !u8 { |
| 33 | _ = a + 1; | 25 | _ = a + 1; |
| 34 | return 1; | 26 | return 1; |
| 35 | } | 27 | } |
| 36 | pub const Panic = struct { | 28 | pub const panic = std.debug.FullPanic(myPanic); |
| 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 | }; | ||
| 45 | fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { | 29 | fn myPanic(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { |
| 46 | std.io.getStdOut().writer().print("new panic message: {s}\n", .{msg}) catch {}; | 30 | std.io.getStdOut().writer().print("new panic message: {s}\n", .{msg}) catch {}; |
| 47 | std.process.exit(0); | 31 | std.process.exit(0); |
| ... | @@ -57,15 +41,7 @@ pub fn main() !u8 { | ... | @@ -57,15 +41,7 @@ pub fn main() !u8 { |
| 57 | _ = a + 1; | 41 | _ = a + 1; |
| 58 | return 1; | 42 | return 1; |
| 59 | } | 43 | } |
| 60 | pub const Panic = struct { | 44 | pub const panic = std.debug.FullPanic(myPanicNew); |
| 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 | }; | ||
| 69 | fn myPanicNew(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { | 45 | fn myPanicNew(msg: []const u8, _: ?*std.builtin.StackTrace, _: ?usize) noreturn { |
| 70 | std.io.getStdOut().writer().print("third panic message: {s}\n", .{msg}) catch {}; | 46 | std.io.getStdOut().writer().print("third panic message: {s}\n", .{msg}) catch {}; |
| 71 | std.process.exit(0); | 47 | 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 | ||
| 6 | pub fn main() !u8 { | ||
| 7 | var a: u8 = undefined; | ||
| 8 | a = 255; | ||
| 9 | _ = a + 1; | ||
| 10 | return 1; | ||
| 11 | } | ||
| 12 | const no_panic = std.debug.no_panic; | ||
| 13 | pub 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 | }; | ||
| 43 | fn 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 | } | ||
| 47 | const std = @import("std"); | ||
| 48 | #expect_stdout="panic message: integer overflow\n" | ||
| 49 | |||
| 50 | #update=change the panic handler body | ||
| 51 | #file=main.zig | ||
| 52 | pub fn main() !u8 { | ||
| 53 | var a: u8 = undefined; | ||
| 54 | a = 255; | ||
| 55 | _ = a + 1; | ||
| 56 | return 1; | ||
| 57 | } | ||
| 58 | const no_panic = std.debug.no_panic; | ||
| 59 | pub 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 | }; | ||
| 89 | fn 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 | } | ||
| 93 | const 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 | ||
| 98 | pub fn main() !u8 { | ||
| 99 | var a: u8 = undefined; | ||
| 100 | a = 255; | ||
| 101 | _ = a + 1; | ||
| 102 | return 1; | ||
| 103 | } | ||
| 104 | const no_panic = std.debug.no_panic; | ||
| 105 | pub 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 | }; | ||
| 136 | fn 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 | } | ||
| 140 | const std = @import("std"); | ||
| 141 | #expect_stdout="third panic message: integer overflow\n" | ||