diff --git a/lib/std/debug.zig b/lib/std/debug.zig index faeed5f667c9a8dc4ec0f38ef2a829b5f42dff3c..59a8dcd9eae1cf7ba40a1e5e9c50a683186c322c 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -151,6 +151,10 @@ pub fn FullPanic(comptime panicFn: fn ([]const u8, ?usize) noreturn) type { @branchHint(.cold); call("invalid error code", @returnAddress()); } + pub fn unexpectedErrorCode(err: anyerror) noreturn { + @branchHint(.cold); + std.debug.panicExtra(@returnAddress(), "unexpected error code, found error.{s}", .{@errorName(err)}); + } pub fn integerOutOfBounds() noreturn { @branchHint(.cold); call("integer does not fit in destination type", @returnAddress()); diff --git a/lib/std/debug/no_panic.zig b/lib/std/debug/no_panic.zig index d47c9799a990e0d53cdf61e735b008deb355fd44..772fb7e496c44a4bf9f566ff17d49826b319cceb 100644 --- a/lib/std/debug/no_panic.zig +++ b/lib/std/debug/no_panic.zig @@ -65,6 +65,11 @@ pub fn invalidErrorCode() noreturn { @trap(); } +pub fn unexpectedErrorCode(_: anyerror) noreturn { + @branchHint(.cold); + @trap(); +} + pub fn integerOutOfBounds() noreturn { @branchHint(.cold); @trap(); diff --git a/lib/std/debug/simple_panic.zig b/lib/std/debug/simple_panic.zig index af7231251aa0e9bd94ef1eef36280d110b4d2019..8453aadbb985766f749199c0bac617cb858afe04 100644 --- a/lib/std/debug/simple_panic.zig +++ b/lib/std/debug/simple_panic.zig @@ -20,110 +20,141 @@ pub fn call(msg: []const u8, ra: ?usize) noreturn { } pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn { + @branchHint(.cold); _ = found; call("sentinel mismatch", null); } pub fn unwrapError(err: anyerror) noreturn { + @branchHint(.cold); _ = &err; call("attempt to unwrap error", null); } pub fn outOfBounds(index: usize, len: usize) noreturn { + @branchHint(.cold); _ = index; _ = len; call("index out of bounds", null); } pub fn startGreaterThanEnd(start: usize, end: usize) noreturn { + @branchHint(.cold); _ = start; _ = end; call("start index is larger than end index", null); } pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn { + @branchHint(.cold); _ = accessed; call("access of inactive union field", null); } pub fn sliceCastLenRemainder(src_len: usize) noreturn { + @branchHint(.cold); _ = src_len; call("slice length does not divide exactly into destination elements", null); } pub fn reachedUnreachable() noreturn { + @branchHint(.cold); call("reached unreachable code", null); } pub fn unwrapNull() noreturn { + @branchHint(.cold); call("attempt to use null value", null); } pub fn castToNull() noreturn { + @branchHint(.cold); call("cast causes pointer to be null", null); } pub fn incorrectAlignment() noreturn { + @branchHint(.cold); call("incorrect alignment", null); } pub fn invalidErrorCode() noreturn { + @branchHint(.cold); call("invalid error code", null); } +pub fn unexpectedErrorCode(err: anyerror) noreturn { + @branchHint(.cold); + _ = err; + call("unexpected error code", null); +} + pub fn integerOutOfBounds() noreturn { + @branchHint(.cold); call("integer does not fit in destination type", null); } pub fn integerOverflow() noreturn { + @branchHint(.cold); call("integer overflow", null); } pub fn shlOverflow() noreturn { + @branchHint(.cold); call("left shift overflowed bits", null); } pub fn shrOverflow() noreturn { + @branchHint(.cold); call("right shift overflowed bits", null); } pub fn divideByZero() noreturn { + @branchHint(.cold); call("division by zero", null); } pub fn exactDivisionRemainder() noreturn { + @branchHint(.cold); call("exact division produced remainder", null); } pub fn integerPartOutOfBounds() noreturn { + @branchHint(.cold); call("integer part of floating point value out of bounds", null); } pub fn corruptSwitch() noreturn { + @branchHint(.cold); call("switch on corrupt value", null); } pub fn shiftRhsTooBig() noreturn { + @branchHint(.cold); call("shift amount is greater than the type size", null); } pub fn invalidEnumValue() noreturn { + @branchHint(.cold); call("invalid enum value", null); } pub fn forLenMismatch() noreturn { + @branchHint(.cold); call("for loop over objects with non-equal lengths", null); } pub fn copyLenMismatch() noreturn { + @branchHint(.cold); call("source and destination have non-equal lengths", null); } pub fn memcpyAlias() noreturn { + @branchHint(.cold); call("@memcpy arguments alias", null); } pub fn noreturnReturned() noreturn { + @branchHint(.cold); call("'noreturn' function returned", null); } diff --git a/src/Sema.zig b/src/Sema.zig index 96bb93f02bcd78185e14c04f40ab832fc09868b4..b2bdfc6abf88324c01e74d78dae9473c5143ac8e 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -21675,16 +21675,16 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData const is_zero = try block.addBinOp(.cmp_eq, err_int_inst, zero_err); if (result == .disjoint) { // Error must be zero. - try sema.addSafetyCheck(block, src, is_zero, .invalid_error_code); + try sema.addSafetyCheckCall(block, src, is_zero, .@"panic.unexpectedErrorCode", &.{err_code_inst}); } else { // Error must be in destination set or zero. const has_value = try block.addTyOp(.error_set_has_value, dest_err_ty, err_int_inst); const ok = try block.addBinOp(.bit_or, has_value, is_zero); - try sema.addSafetyCheck(block, src, ok, .invalid_error_code); + try sema.addSafetyCheckCall(block, src, ok, .@"panic.unexpectedErrorCode", &.{err_code_inst}); } } else { const ok = try block.addTyOp(.error_set_has_value, dest_err_ty, err_int_inst); - try sema.addSafetyCheck(block, src, ok, .invalid_error_code); + try sema.addSafetyCheckCall(block, src, ok, .@"panic.unexpectedErrorCode", &.{err_code_inst}); } } @@ -35031,7 +35031,9 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.StdLangDecl) CompileError!Typ }), // `fn (anyerror) noreturn` - .@"panic.unwrapError" => try pt.funcType(.{ + .@"panic.unwrapError", + .@"panic.unexpectedErrorCode", + => try pt.funcType(.{ .param_types = &.{.anyerror_type}, .return_type = .noreturn_type, }), diff --git a/src/Zcu.zig b/src/Zcu.zig index 0c231862cb0720fec4419115e08b712eacbdcf6f..92659d3253b60fb26eddac3eadf3ce9ec6ba1499 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -503,6 +503,7 @@ pub const StdLangDecl = enum { @"panic.castToNull", @"panic.incorrectAlignment", @"panic.invalidErrorCode", + @"panic.unexpectedErrorCode", @"panic.integerOutOfBounds", @"panic.integerOverflow", @"panic.shlOverflow", @@ -593,6 +594,7 @@ pub const StdLangDecl = enum { .@"panic.castToNull", .@"panic.incorrectAlignment", .@"panic.invalidErrorCode", + .@"panic.unexpectedErrorCode", .@"panic.integerOutOfBounds", .@"panic.integerOverflow", .@"panic.shlOverflow", diff --git a/test/cases/compile_errors/bad_panic_call_signature.zig b/test/cases/compile_errors/bad_panic_call_signature.zig index 6d88f1b8781c6db162037a42564cbe3fefc06179..fdfc8a8c3bad266235f5458dbe476bded279352c 100644 --- a/test/cases/compile_errors/bad_panic_call_signature.zig +++ b/test/cases/compile_errors/bad_panic_call_signature.zig @@ -15,6 +15,7 @@ pub const panic = struct { pub const castToNull = simple_panic.castToNull; pub const incorrectAlignment = simple_panic.incorrectAlignment; pub const invalidErrorCode = simple_panic.invalidErrorCode; + pub const unexpectedErrorCode = simple_panic.unexpectedErrorCode; pub const integerOutOfBounds = simple_panic.integerOutOfBounds; pub const integerOverflow = simple_panic.integerOverflow; pub const shlOverflow = simple_panic.shlOverflow; diff --git a/test/cases/compile_errors/bad_panic_generic_signature.zig b/test/cases/compile_errors/bad_panic_generic_signature.zig index 8ef4810745ce45855bad0262e1a1bef0ca5db414..0dba45036e36bb73e44c046a8a3b0a8dd645dab9 100644 --- a/test/cases/compile_errors/bad_panic_generic_signature.zig +++ b/test/cases/compile_errors/bad_panic_generic_signature.zig @@ -11,6 +11,7 @@ pub const panic = struct { pub const castToNull = simple_panic.castToNull; pub const incorrectAlignment = simple_panic.incorrectAlignment; pub const invalidErrorCode = simple_panic.invalidErrorCode; + pub const unexpectedErrorCode = simple_panic.unexpectedErrorCode; pub const integerOutOfBounds = simple_panic.integerOutOfBounds; pub const integerOverflow = simple_panic.integerOverflow; pub const shlOverflow = simple_panic.shlOverflow; diff --git a/test/cases/safety/@errorCast error not present in destination.zig b/test/cases/safety/@errorCast error not present in destination.zig index 3ae83186023587a707594a45f89e723c338265c9..2e0e4f22538db11499f89cc82b996ff20a582c34 100644 --- a/test/cases/safety/@errorCast error not present in destination.zig +++ b/test/cases/safety/@errorCast error not present in destination.zig @@ -2,7 +2,7 @@ const std = @import("std"); pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { _ = stack_trace; - if (std.mem.eql(u8, message, "invalid error code")) { + if (std.mem.eql(u8, message, "unexpected error code, found error.B")) { std.process.exit(0); } std.process.exit(1); diff --git a/test/cases/safety/@errorCast error union casted to disjoint set.zig b/test/cases/safety/@errorCast error union casted to disjoint set.zig index 0bf9311be764390a109d85f146868a1ab6a5b265..2f8238698a8afee3d9cdd7ba05f0f274b05b6241 100644 --- a/test/cases/safety/@errorCast error union casted to disjoint set.zig +++ b/test/cases/safety/@errorCast error union casted to disjoint set.zig @@ -2,7 +2,7 @@ const std = @import("std"); pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { _ = stack_trace; - if (std.mem.eql(u8, message, "invalid error code")) { + if (std.mem.eql(u8, message, "unexpected error code, found error.Bar")) { std.process.exit(0); } std.process.exit(1); diff --git a/test/incremental/change_panic_handler_explicit b/test/incremental/change_panic_handler_explicit index f748a57afc43e7d18e5458549a18c173d21dc56c..3735cfd86c0116ce130481c56f60d6816174d00f 100644 --- a/test/incremental/change_panic_handler_explicit +++ b/test/incremental/change_panic_handler_explicit @@ -23,6 +23,7 @@ pub const panic = struct { pub const castToNull = no_panic.castToNull; pub const incorrectAlignment = no_panic.incorrectAlignment; pub const invalidErrorCode = no_panic.invalidErrorCode; + pub const unexpectedErrorCode = no_panic.unexpectedErrorCode; pub const integerOutOfBounds = no_panic.integerOutOfBounds; pub const shlOverflow = no_panic.shlOverflow; pub const shrOverflow = no_panic.shrOverflow; @@ -72,6 +73,7 @@ pub const panic = struct { pub const castToNull = no_panic.castToNull; pub const incorrectAlignment = no_panic.incorrectAlignment; pub const invalidErrorCode = no_panic.invalidErrorCode; + pub const unexpectedErrorCode = no_panic.unexpectedErrorCode; pub const integerOutOfBounds = no_panic.integerOutOfBounds; pub const shlOverflow = no_panic.shlOverflow; pub const shrOverflow = no_panic.shrOverflow; @@ -121,6 +123,7 @@ pub const panic = struct { pub const castToNull = no_panic.castToNull; pub const incorrectAlignment = no_panic.incorrectAlignment; pub const invalidErrorCode = no_panic.invalidErrorCode; + pub const unexpectedErrorCode = no_panic.unexpectedErrorCode; pub const integerOutOfBounds = no_panic.integerOutOfBounds; pub const shlOverflow = no_panic.shlOverflow; pub const shrOverflow = no_panic.shrOverflow;