new unreachable syntax

* `noreturn` is the primitive type.
 * `unreachable` is a control flow keyword.
 * `@unreachable()` builtin function is deleted.

closes #214
This commit is contained in:
Andrew Kelley 2017-03-26 04:58:48 -04:00
parent 22e6bfca96
commit 451ce09067
35 changed files with 130 additions and 192 deletions

View File

@ -155,7 +155,7 @@ GotoExpression = "goto" Symbol
GroupedExpression = "(" Expression ")"
KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this"
KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this" | "unreachable"
ContainerDecl = option("extern" | "packed") ("struct" | "enum" | "union") "{" many(ContainerMember) "}"
@ -213,60 +213,6 @@ f32 float 32-bit floating point
f64 double 64-bit floating point
```
### Boolean Type
The boolean type has the name `bool` and represents either true or false.
### Function Type
TODO
### Fixed-Size Array Type
Example: The string `"aoeu"` has type `[4]u8`.
The size is known at compile time and is part of the type.
### Slice Type
A slice can be obtained with the slicing syntax: `array[start...end]`
Example: `"aoeu"[0...2]` has type `[]u8`.
### Struct Type
TODO
### Enum Type
TODO
### Maybe Type
TODO
### Pure Error Type
TODO
### Error Union Type
TODO
### Pointer Type
TODO
### Unreachable Type
The unreachable type has the name `unreachable`. TODO explanation
### Void Type
The void type has the name `void`. void types are zero bits and are omitted
from codegen.
## Expressions
### Literals
@ -347,31 +293,6 @@ has a terminating null byte.
Floating point | 123.0E+77 | Optional
Hex floating point | 0x103.70p-5 | Optional
### Identifiers
TODO
### Declarations
Declarations have type `void`.
#### Function Declarations
TODO
#### Variable Declarations
TODO
#### Struct Declarations
TODO
#### Enum Declarations
TODO
## Built-in Functions
Built-in functions are prefixed with `@`. Remember that the `comptime` keyword on
@ -682,10 +603,6 @@ code.
This function returns an integer type with the given signness and bit count.
### @setFnTest(func)
Makes the target function a test function.
### @setDebugSafety(scope, safety_on: bool)
Sets a whether we want debug safety checks on for a given scope.

View File

@ -16,7 +16,7 @@ syn keyword zigRepeat while for
syn keyword zigConstant null undefined this
syn keyword zigKeyword fn use test
syn keyword zigType bool f32 f64 void Unreachable type error
syn keyword zigType bool f32 f64 void noreturn type error
syn keyword zigType i8 u8 i16 u16 i32 u32 i64 u64 isize usize
syn keyword zigType c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong c_long_double

View File

@ -334,6 +334,7 @@ enum NodeType {
NodeTypeNullLiteral,
NodeTypeUndefinedLiteral,
NodeTypeThisLiteral,
NodeTypeUnreachable,
NodeTypeIfBoolExpr,
NodeTypeIfVarExpr,
NodeTypeWhileExpr,
@ -758,6 +759,9 @@ struct AstNodeBreakExpr {
struct AstNodeContinueExpr {
};
struct AstNodeUnreachableExpr {
};
struct AstNodeArrayType {
AstNode *size;
@ -827,6 +831,7 @@ struct AstNode {
AstNodeBoolLiteral bool_literal;
AstNodeBreakExpr break_expr;
AstNodeContinueExpr continue_expr;
AstNodeUnreachableExpr unreachable_expr;
AstNodeArrayType array_type;
AstNodeErrorType error_type;
AstNodeTypeLiteral type_literal;
@ -1173,7 +1178,6 @@ enum BuiltinFnId {
BuiltinFnIdDivExact,
BuiltinFnIdTruncate,
BuiltinFnIdIntType,
BuiltinFnIdUnreachable,
BuiltinFnIdSetFnVisible,
BuiltinFnIdSetDebugSafety,
BuiltinFnIdAlloca,

View File

@ -2110,6 +2110,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
case NodeTypeGoto:
case NodeTypeBreak:
case NodeTypeContinue:
case NodeTypeUnreachable:
case NodeTypeAsmExpr:
case NodeTypeFieldAccessExpr:
case NodeTypeStructField:

View File

@ -216,6 +216,8 @@ static const char *node_type_str(NodeType node_type) {
return "Break";
case NodeTypeContinue:
return "Continue";
case NodeTypeUnreachable:
return "Unreachable";
case NodeTypeAsmExpr:
return "AsmExpr";
case NodeTypeFieldAccessExpr:
@ -890,6 +892,11 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
fprintf(ar->f, "continue");
break;
}
case NodeTypeUnreachable:
{
fprintf(ar->f, "unreachable");
break;
}
case NodeTypeSliceExpr:
{
render_node_ungrouped(ar, node->data.slice_expr.array_ref_expr);

View File

@ -3786,7 +3786,7 @@ static void define_builtin_types(CodeGen *g) {
TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUnreachable);
entry->type_ref = LLVMVoidType();
entry->zero_bits = true;
buf_init_from_str(&entry->name, "unreachable");
buf_init_from_str(&entry->name, "noreturn");
entry->di_type = g->builtin_types.entry_void->di_type;
g->builtin_types.entry_unreachable = entry;
g->primitive_type_table.put(&entry->name, entry);
@ -4096,7 +4096,6 @@ static void define_builtin_fns(CodeGen *g) {
create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
create_builtin_fn(g, BuiltinFnIdIntType, "intType", 2);
create_builtin_fn(g, BuiltinFnIdUnreachable, "unreachable", 0);
create_builtin_fn(g, BuiltinFnIdSetFnVisible, "setFnVisible", 2);
create_builtin_fn(g, BuiltinFnIdSetDebugSafety, "setDebugSafety", 2);
create_builtin_fn(g, BuiltinFnIdAlloca, "alloca", 2);

View File

@ -3751,8 +3751,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
switch (builtin_fn->id) {
case BuiltinFnIdInvalid:
zig_unreachable();
case BuiltinFnIdUnreachable:
return ir_build_unreachable(irb, scope, node);
case BuiltinFnIdTypeof:
{
AstNode *arg_node = node->data.fn_call_expr.params.at(0);
@ -5467,6 +5465,8 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
return ir_lval_wrap(irb, scope, ir_gen_break(irb, scope, node), lval);
case NodeTypeContinue:
return ir_lval_wrap(irb, scope, ir_gen_continue(irb, scope, node), lval);
case NodeTypeUnreachable:
return ir_lval_wrap(irb, scope, ir_build_unreachable(irb, scope, node), lval);
case NodeTypeDefer:
return ir_lval_wrap(irb, scope, ir_gen_defer(irb, scope, node), lval);
case NodeTypeSliceExpr:

View File

@ -705,7 +705,7 @@ static AstNode *ast_parse_try_expr(ParseContext *pc, size_t *token_index, bool m
/*
PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this"
KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "error" | "type" | "this" | "unreachable"
*/
static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
Token *token = &pc->tokens->at(*token_index);
@ -757,6 +757,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
AstNode *node = ast_create_node(pc, NodeTypeThisLiteral, token);
*token_index += 1;
return node;
} else if (token->id == TokenIdKeywordUnreachable) {
AstNode *node = ast_create_node(pc, NodeTypeUnreachable, token);
*token_index += 1;
return node;
} else if (token->id == TokenIdKeywordType) {
AstNode *node = ast_create_node(pc, NodeTypeTypeLiteral, token);
*token_index += 1;
@ -2728,6 +2732,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
case NodeTypeContinue:
// none
break;
case NodeTypeUnreachable:
// none
break;
case NodeTypeAsmExpr:
for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1) {
AsmInput *asm_input = node->data.asm_expr.input_list.at(i);

View File

@ -140,6 +140,7 @@ static const struct ZigKeyword zig_keywords[] = {
{"type", TokenIdKeywordType},
{"undefined", TokenIdKeywordUndefined},
{"union", TokenIdKeywordUnion},
{"unreachable", TokenIdKeywordUnreachable},
{"use", TokenIdKeywordUse},
{"var", TokenIdKeywordVar},
{"volatile", TokenIdKeywordVolatile},
@ -1516,6 +1517,7 @@ const char * token_name(TokenId id) {
case TokenIdKeywordType: return "type";
case TokenIdKeywordUndefined: return "undefined";
case TokenIdKeywordUnion: return "union";
case TokenIdKeywordUnreachable: return "unreachable";
case TokenIdKeywordUse: return "use";
case TokenIdKeywordVar: return "var";
case TokenIdKeywordVolatile: return "volatile";

View File

@ -81,6 +81,7 @@ enum TokenId {
TokenIdKeywordType,
TokenIdKeywordUndefined,
TokenIdKeywordUnion,
TokenIdKeywordUnreachable,
TokenIdKeywordUse,
TokenIdKeywordVar,
TokenIdKeywordVolatile,

View File

@ -16,10 +16,10 @@ const exit = switch(@compileVar("os")) {
var argc: usize = undefined;
var argv: &&u8 = undefined;
export nakedcc fn _start() -> unreachable {
export nakedcc fn _start() -> noreturn {
@setFnVisible(this, want_start_symbol);
if (!want_start_symbol) {
@unreachable();
unreachable;
}
switch (@compileVar("arch")) {
@ -45,7 +45,7 @@ fn callMain() -> %void {
return root.main(args);
}
fn callMainAndExit() -> unreachable {
fn callMainAndExit() -> noreturn {
callMain() %% exit(1);
exit(0);
}
@ -53,7 +53,7 @@ fn callMainAndExit() -> unreachable {
export fn main(c_argc: i32, c_argv: &&u8) -> i32 {
@setFnVisible(this, want_main_symbol);
if (!want_main_symbol) {
@unreachable();
unreachable;
}
argc = usize(c_argc);

View File

@ -31,6 +31,6 @@ export fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) {
}
// Avoid dragging in the debug safety mechanisms into this .o file.
pub fn panic(message: []const u8) -> unreachable {
@unreachable();
pub fn panic(message: []const u8) -> noreturn {
unreachable;
}

View File

@ -7,7 +7,7 @@ pub use switch(@compileVar("os")) {
else => empty_import,
};
pub extern fn abort() -> unreachable;
pub extern fn abort() -> noreturn;
const empty_import = @import("empty.zig");

View File

@ -1,10 +1,10 @@
// Avoid dragging in the debug safety mechanisms into this .o file,
// unless we're trying to test this file.
pub fn panic(message: []const u8) -> unreachable {
pub fn panic(message: []const u8) -> noreturn {
if (@compileVar("is_test")) {
@import("std").debug.panic(message);
} else {
@unreachable();
unreachable;
}
}
@ -259,7 +259,7 @@ export nakedcc fn __aeabi_uidivmod() {
\\ add sp, sp, #4
\\ pop { pc }
::: "r2", "r1");
@unreachable();
unreachable;
}
@setFnVisible(this, false);
@ -511,5 +511,5 @@ fn test_one_udivsi3(a: su_int, b: su_int, expected_q: su_int) {
fn assert(ok: bool) {
if (!ok) @unreachable();
if (!ok) unreachable;
}

View File

@ -48,9 +48,9 @@ pub const SIGPWR = 30;
pub const SIGSYS = 31;
pub const SIGUNUSED = SIGSYS;
pub fn exit(status: usize) -> unreachable {
pub fn exit(status: usize) -> noreturn {
_ = arch.syscall1(arch.SYS_exit, status);
@unreachable()
unreachable
}
/// Get the errno from a syscall return value, or 0 for no error.

View File

@ -10,12 +10,12 @@ error InvalidDebugInfo;
error UnsupportedDebugInfo;
pub fn assert(ok: bool) {
if (!ok) @unreachable()
if (!ok) unreachable
}
var panicking = false;
/// This is the default panic implementation.
pub coldcc fn panic(message: []const u8) -> unreachable {
pub coldcc fn panic(message: []const u8) -> noreturn {
// TODO
// if (@atomicRmw(AtomicOp.XChg, &panicking, true, AtomicOrder.SeqCst)) { }
if (panicking) {
@ -252,7 +252,7 @@ fn parseFormValueTargetAddrSize(in_stream: &io.InStream) -> %u64 {
} else if (@sizeOf(usize) == 8) {
%return in_stream.readIntLe(u64)
} else {
@unreachable();
unreachable;
};
}

View File

@ -287,7 +287,7 @@ fn digitToChar(digit: u8, uppercase: bool) -> u8 {
return switch (digit) {
0 ... 9 => digit + '0',
10 ... 35 => digit + ((if (uppercase) u8('A') else u8('a')) - 10),
else => @unreachable(),
else => unreachable,
};
}
@ -316,9 +316,9 @@ fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, width: u
test "testParseU64DigitTooBig" {
parseUnsigned(u64, "123a", 10) %% |err| {
if (err == error.InvalidChar) return;
@unreachable();
unreachable;
};
@unreachable();
unreachable;
}
test "testParseUnsignedComptime" {

View File

@ -50,7 +50,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
return entry;
}
}
@unreachable() // no next item
unreachable // no next item
}
};
@ -125,9 +125,9 @@ pub fn HashMap(comptime K: type, comptime V: type,
entry.distance_from_start_index -= 1;
entry = next_entry;
}
@unreachable() // shifting everything in the table
unreachable // shifting everything in the table
}}
@unreachable() // key not found
unreachable // key not found
}
pub fn entryIterator(hm: &Self) -> Iterator {
@ -198,7 +198,7 @@ pub fn HashMap(comptime K: type, comptime V: type,
};
return;
}
@unreachable() // put into a full map
unreachable // put into a full map
}
fn internalGet(hm: &Self, key: K) -> ?&Entry {

View File

@ -129,7 +129,7 @@ pub const OutStream = struct {
if (write_err > 0) {
return switch (write_err) {
errno.EINTR => continue,
errno.EINVAL => @unreachable(),
errno.EINVAL => unreachable,
errno.EDQUOT => error.DiskQuota,
errno.EFBIG => error.FileTooBig,
errno.EIO => error.Io,
@ -171,8 +171,8 @@ pub const InStream = struct {
return switch (err) {
errno.EINTR => continue,
errno.EFAULT => @unreachable(),
errno.EINVAL => @unreachable(),
errno.EFAULT => unreachable,
errno.EINVAL => unreachable,
errno.EACCES => error.BadPerm,
errno.EFBIG, errno.EOVERFLOW => error.FileTooBig,
errno.EISDIR => error.IsDir,
@ -235,8 +235,8 @@ pub const InStream = struct {
switch (read_err) {
errno.EINTR => continue,
errno.EINVAL => @unreachable(),
errno.EFAULT => @unreachable(),
errno.EINVAL => unreachable,
errno.EFAULT => unreachable,
errno.EBADF => return error.BadFd,
errno.EIO => return error.Io,
else => return error.Unexpected,

View File

@ -297,9 +297,9 @@ pub fn lseek(fd: i32, offset: usize, ref_pos: usize) -> usize {
arch.syscall3(arch.SYS_lseek, usize(fd), offset, ref_pos)
}
pub fn exit(status: i32) -> unreachable {
pub fn exit(status: i32) -> noreturn {
_ = arch.syscall1(arch.SYS_exit, usize(status));
@unreachable()
unreachable
}
pub fn getrandom(buf: &u8, count: usize, flags: u32) -> usize {

View File

@ -57,7 +57,7 @@ pub fn abs(x: var) -> @typeOf(x) {
} else if (@isFloat(T)) {
@compileError("TODO implement abs for floats");
} else {
@unreachable();
unreachable;
}
}
fn getReturnTypeForAbs(comptime T: type) -> type {

View File

@ -21,8 +21,8 @@ const Connection = struct {
const send_err = linux.getErrno(send_ret);
switch (send_err) {
0 => return send_ret,
errno.EINVAL => @unreachable(),
errno.EFAULT => @unreachable(),
errno.EINVAL => unreachable,
errno.EFAULT => unreachable,
errno.ECONNRESET => return error.ConnectionReset,
errno.EINTR => return error.SigInterrupt,
// TODO there are more possible errors
@ -35,8 +35,8 @@ const Connection = struct {
const recv_err = linux.getErrno(recv_ret);
switch (recv_err) {
0 => return buf[0...recv_ret],
errno.EINVAL => @unreachable(),
errno.EFAULT => @unreachable(),
errno.EINVAL => unreachable,
errno.EFAULT => unreachable,
errno.ENOTSOCK => return error.NotSocket,
errno.EINTR => return error.SigInterrupt,
errno.ENOMEM => return error.NoMem,
@ -50,7 +50,7 @@ const Connection = struct {
pub fn close(c: Connection) -> %void {
switch (linux.getErrno(linux.close(c.socket_fd))) {
0 => return,
errno.EBADF => @unreachable(),
errno.EBADF => unreachable,
errno.EINTR => return error.SigInterrupt,
errno.EIO => return error.Io,
else => return error.Unexpected,
@ -74,7 +74,7 @@ pub fn lookup(hostname: []const u8, out_addrs: []Address) -> %[]Address {
// if (family != AF_INET)
// buf[cnt++] = (struct address){ .family = AF_INET6, .addr = { [15] = 1 } };
//
@unreachable() // TODO
unreachable // TODO
}
// TODO
@ -86,7 +86,7 @@ pub fn lookup(hostname: []const u8, out_addrs: []Address) -> %[]Address {
// else => {},
//};
@unreachable() // TODO
unreachable // TODO
}
pub fn connectAddr(addr: &Address, port: u16) -> %Connection {
@ -114,7 +114,7 @@ pub fn connectAddr(addr: &Address, port: u16) -> %Connection {
@memcpy(&os_addr.addr[0], &addr.addr[0], 16);
linux.connect(socket_fd, (&linux.sockaddr)(&os_addr), @sizeOf(linux.sockaddr_in6))
} else {
@unreachable()
unreachable
};
const connect_err = linux.getErrno(connect_ret);
if (connect_err > 0) {
@ -324,11 +324,11 @@ fn parseIp4(buf: []const u8) -> %u32 {
// @setFnTest(this);
//
// assert(%%parseIp4("127.0.0.1") == endian.swapIfLe(u32, 0x7f000001));
// switch (parseIp4("256.0.0.1")) { Overflow => {}, else => @unreachable(), }
// switch (parseIp4("x.0.0.1")) { InvalidChar => {}, else => @unreachable(), }
// switch (parseIp4("127.0.0.1.1")) { JunkAtEnd => {}, else => @unreachable(), }
// switch (parseIp4("127.0.0.")) { Incomplete => {}, else => @unreachable(), }
// switch (parseIp4("100..0.1")) { InvalidChar => {}, else => @unreachable(), }
// switch (parseIp4("256.0.0.1")) { Overflow => {}, else => unreachable, }
// switch (parseIp4("x.0.0.1")) { InvalidChar => {}, else => unreachable, }
// switch (parseIp4("127.0.0.1.1")) { JunkAtEnd => {}, else => unreachable, }
// switch (parseIp4("127.0.0.")) { Incomplete => {}, else => unreachable, }
// switch (parseIp4("100..0.1")) { InvalidChar => {}, else => unreachable, }
//}
//
//fn testParseIp6() {

View File

@ -46,8 +46,8 @@ pub fn getRandomBytes(buf: []u8) -> %void {
};
if (err > 0) {
return switch (err) {
errno.EINVAL => @unreachable(),
errno.EFAULT => @unreachable(),
errno.EINVAL => unreachable,
errno.EFAULT => unreachable,
errno.EINTR => continue,
else => error.Unexpected,
}
@ -59,7 +59,7 @@ pub fn getRandomBytes(buf: []u8) -> %void {
/// Raises a signal in the current kernel thread, ending its execution.
/// If linking against libc, this calls the abort() libc function. Otherwise
/// it uses the zig standard library implementation.
pub coldcc fn abort() -> unreachable {
pub coldcc fn abort() -> noreturn {
if (linking_libc) {
c.abort();
}

View File

@ -3,7 +3,7 @@
// If this file wants to import other files *by name*, support for that would
// have to be added in the compiler.
pub coldcc fn panic(message: []const u8) -> unreachable {
pub coldcc fn panic(message: []const u8) -> noreturn {
if (@compileVar("os") == Os.freestanding) {
while (true) {}
} else {

View File

@ -16,7 +16,7 @@ test "enumType" {
test "enumAsReturnValue" {
switch (returnAnInt(13)) {
Foo.One => |value| assert(value == 13),
else => @unreachable(),
else => unreachable,
}
}
@ -51,13 +51,13 @@ test "constantEnumWithPayload" {
fn shouldBeEmpty(x: &const AnEnumWithPayload) {
switch (*x) {
AnEnumWithPayload.Empty => {},
else => @unreachable(),
else => unreachable,
}
}
fn shouldBeNotEmpty(x: &const AnEnumWithPayload) {
switch (*x) {
AnEnumWithPayload.Empty => @unreachable(),
AnEnumWithPayload.Empty => unreachable,
else => {},
}
}

View File

@ -48,7 +48,7 @@ error AnError;
error AnError;
error SecondError;
fn shouldBeNotEqual(a: error, b: error) {
if (a == b) @unreachable()
if (a == b) unreachable
}

View File

@ -13,7 +13,7 @@ test "localVariables" {
}
fn testLocVars(b: i32) {
const a: i32 = 1;
if (a + b != 3) @unreachable();
if (a + b != 3) unreachable;
}
@ -72,8 +72,8 @@ test "implicitCastFnUnreachableReturn" {
fn wantsFnWithVoid(f: fn()) { }
fn fnWithUnreachable() -> unreachable {
@unreachable()
fn fnWithUnreachable() -> noreturn {
unreachable
}

View File

@ -12,7 +12,7 @@ test "continueInForLoop" {
}
break;
}
if (sum != 6) @unreachable()
if (sum != 6) unreachable
}
test "forLoopWithPointerElemVar" {

View File

@ -30,7 +30,7 @@ exit:
if (it_worked) {
return;
}
@unreachable();
unreachable;
entry:
defer it_worked = true;
if (b) goto exit;

View File

@ -6,20 +6,20 @@ test "ifStatements" {
}
fn shouldBeEqual(a: i32, b: i32) {
if (a != b) {
@unreachable();
unreachable;
} else {
return;
}
}
fn firstEqlThird(a: i32, b: i32, c: i32) {
if (a == b) {
@unreachable();
unreachable;
} else if (b == c) {
@unreachable();
unreachable;
} else if (a == c) {
return;
} else {
@unreachable();
unreachable;
}
}

View File

@ -163,7 +163,7 @@ test "memcpyAndMemsetIntrinsics" {
@memset(&foo[0], 'A', foo.len);
@memcpy(&bar[0], &foo[0], bar.len);
if (bar[11] != 'A') @unreachable();
if (bar[11] != 'A') unreachable;
}
test "builtinStaticEval" {
@ -178,13 +178,13 @@ test "slicing" {
var slice = array[5...10];
if (slice.len != 5) @unreachable();
if (slice.len != 5) unreachable;
const ptr = &slice[0];
if (ptr[0] != 1234) @unreachable();
if (ptr[0] != 1234) unreachable;
var slice_rest = array[10...];
if (slice_rest.len != 10) @unreachable();
if (slice_rest.len != 10) unreachable;
}
@ -344,7 +344,7 @@ fn test3_1(f: &const Test3Foo) {
assert(pt.x == 3);
assert(pt.y == 4);
},
else => @unreachable(),
else => unreachable,
}
}
fn test3_2(f: &const Test3Foo) {
@ -352,7 +352,7 @@ fn test3_2(f: &const Test3Foo) {
Test3Foo.Two => |x| {
assert(x == 13);
},
else => @unreachable(),
else => unreachable,
}
}

View File

@ -7,10 +7,10 @@ test "nullableType" {
if (y) {
// OK
} else {
@unreachable();
unreachable;
}
} else {
@unreachable();
unreachable;
}
const next_x : ?i32 = @generatedCode(null);
@ -21,7 +21,7 @@ test "nullableType" {
const final_x : ?i32 = @generatedCode(13);
const num = final_x ?? @unreachable();
const num = final_x ?? unreachable;
assert(num == 13);
}

View File

@ -55,9 +55,9 @@ const Fruit = enum {
};
fn nonConstSwitchOnEnum(fruit: Fruit) {
switch (fruit) {
Fruit.Apple => @unreachable(),
Fruit.Apple => unreachable,
Fruit.Orange => {},
Fruit.Banana => @unreachable(),
Fruit.Banana => unreachable,
}
}
@ -72,7 +72,7 @@ fn nonConstSwitch(foo: SwitchStatmentFoo) {
SwitchStatmentFoo.C => 3,
SwitchStatmentFoo.D => 4,
};
if (val != 3) @unreachable();
if (val != 3) unreachable;
}
const SwitchStatmentFoo = enum {
A,
@ -95,10 +95,10 @@ const SwitchProngWithVarEnum = enum {
fn switchProngWithVarFn(a: &const SwitchProngWithVarEnum) {
switch(*a) {
SwitchProngWithVarEnum.One => |x| {
if (x != 13) @unreachable();
if (x != 13) unreachable;
},
SwitchProngWithVarEnum.Two => |x| {
if (x != 13.0) @unreachable();
if (x != 13.0) unreachable;
},
SwitchProngWithVarEnum.Meh => |x| {
const v: void = x;

View File

@ -52,7 +52,7 @@ fn failIfTrue(ok: bool) -> %void {
// @setFnTest(this);
//
// try (_ = failIfTrue(true)) {
// @unreachable();
// unreachable;
// } else |err| {
// assert(err == error.ItBroke);
// }

View File

@ -471,8 +471,8 @@ const foo : i32 = 0;
const c = @cImport(@cInclude("stdlib.h"));
export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int {
const a_int = (&i32)(a ?? @unreachable());
const b_int = (&i32)(b ?? @unreachable());
const a_int = (&i32)(a ?? unreachable);
const b_int = (&i32)(b ?? unreachable);
if (*a_int < *b_int) {
-1
} else if (*a_int > *b_int) {
@ -628,9 +628,9 @@ export fn entry() { a(); }
)SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'a'");
add_compile_fail_case("unreachable with return", R"SOURCE(
fn a() -> unreachable {return;}
fn a() -> noreturn {return;}
export fn entry() { a(); }
)SOURCE", 1, ".tmp_source.zig:2:24: error: expected type 'unreachable', found 'void'");
)SOURCE", 1, ".tmp_source.zig:2:21: error: expected type 'noreturn', found 'void'");
add_compile_fail_case("control reaches end of non-void function", R"SOURCE(
fn a() -> i32 {}
@ -656,7 +656,7 @@ export fn entry() { _ = a(); }
)SOURCE", 1, ".tmp_source.zig:2:11: error: use of undeclared identifier 'bogus'");
add_compile_fail_case("pointer to unreachable", R"SOURCE(
fn a() -> &unreachable {}
fn a() -> &noreturn {}
export fn entry() { _ = a(); }
)SOURCE", 1, ".tmp_source.zig:2:12: error: pointer to unreachable not allowed");
@ -724,14 +724,14 @@ export fn f() {
add_compile_fail_case("unreachable variable", R"SOURCE(
export fn f() {
const a : unreachable = {};
const a: noreturn = {};
}
)SOURCE", 1, ".tmp_source.zig:3:15: error: variable of type 'unreachable' not allowed");
)SOURCE", 1, ".tmp_source.zig:3:14: error: variable of type 'noreturn' not allowed");
add_compile_fail_case("unreachable parameter", R"SOURCE(
fn f(a : unreachable) {}
fn f(a: noreturn) {}
export fn entry() { f(); }
)SOURCE", 1, ".tmp_source.zig:2:10: error: parameter of type 'unreachable' not allowed");
)SOURCE", 1, ".tmp_source.zig:2:9: error: parameter of type 'noreturn' not allowed");
add_compile_fail_case("bad assignment target", R"SOURCE(
export fn f() {
@ -1737,7 +1737,7 @@ export fn foo() {
}
fn assert(ok: bool) {
if (!ok) @unreachable();
if (!ok) unreachable;
}
)SOURCE", 2,
".tmp_source.zig:11:14: error: unable to evaluate constant expression",
@ -1830,7 +1830,7 @@ export fn entry() {
static void add_debug_safety_test_cases(void) {
add_debug_safety_case("out of bounds slice access", R"SOURCE(
pub fn panic(message: []const u8) -> unreachable {
pub fn panic(message: []const u8) -> noreturn {
@breakpoint();
while (true) {}
}
@ -1845,7 +1845,7 @@ fn baz(a: i32) { }
)SOURCE");
add_debug_safety_case("integer addition overflow", R"SOURCE(
pub fn panic(message: []const u8) -> unreachable {
pub fn panic(message: []const u8) -> noreturn {
@breakpoint();
while (true) {}
}
@ -1860,7 +1860,7 @@ fn add(a: u16, b: u16) -> u16 {
)SOURCE");
add_debug_safety_case("integer subtraction overflow", R"SOURCE(
pub fn panic(message: []const u8) -> unreachable {
pub fn panic(message: []const u8) -> noreturn {
@breakpoint();
while (true) {}
}
@ -1875,7 +1875,7 @@ fn sub(a: u16, b: u16) -> u16 {
)SOURCE");
add_debug_safety_case("integer multiplication overflow", R"SOURCE(
pub fn panic(message: []const u8) -> unreachable {
pub fn panic(message: []const u8) -> noreturn {
@breakpoint();
while (true) {}
}
@ -1890,7 +1890,7 @@ fn mul(a: u16, b: u16) -> u16 {
)SOURCE");
add_debug_safety_case("integer negation overflow", R"SOURCE(
pub fn panic(message: []const u8) -> unreachable {
pub fn panic(message: []const u8) -> noreturn {
@breakpoint();
while (true) {}
}
@ -1905,7 +1905,7 @@ fn neg(a: i16) -> i16 {
)SOURCE");
add_debug_safety_case("signed integer division overflow", R"SOURCE(
pub fn panic(message: []const u8) -> unreachable {
pub fn panic(message: []const u8) -> noreturn {
@breakpoint();
while (true) {}
}
@ -1920,7 +1920,7 @@ fn div(a: i16, b: i16) -> i16 {
)SOURCE");
add_debug_safety_case("signed shift left overflow", R"SOURCE(
pub fn panic(message: []const u8) -> unreachable {
pub fn panic(message: []const u8) -> noreturn {
@breakpoint();
while (true) {}
}
@ -1935,7 +1935,7 @@ fn shl(a: i16, b: i16) -> i16 {
)SOURCE");
add_debug_safety_case("unsigned shift left overflow", R"SOURCE(
pub fn panic(message: []const u8) -> unreachable {
pub fn panic(message: []const u8) -> noreturn {
@breakpoint();
while (true) {}
}
@ -1950,7 +1950,7 @@ fn shl(a: u16, b: u16) -> u16 {
)SOURCE");
add_debug_safety_case("integer division by zero", R"SOURCE(
pub fn panic(message: []const u8) -> unreachable {
pub fn panic(message: []const u8) -> noreturn {
@breakpoint();
while (true) {}
}
@ -1964,7 +1964,7 @@ fn div0(a: i32, b: i32) -> i32 {
)SOURCE");
add_debug_safety_case("exact division failure", R"SOURCE(
pub fn panic(message: []const u8) -> unreachable {
pub fn panic(message: []const u8) -> noreturn {
@breakpoint();
while (true) {}
}
@ -1979,7 +1979,7 @@ fn divExact(a: i32, b: i32) -> i32 {
)SOURCE");
add_debug_safety_case("cast []u8 to bigger slice of wrong size", R"SOURCE(
pub fn panic(message: []const u8) -> unreachable {
pub fn panic(message: []const u8) -> noreturn {
@breakpoint();
while (true) {}
}
@ -1994,7 +1994,7 @@ fn widenSlice(slice: []const u8) -> []const i32 {
)SOURCE");
add_debug_safety_case("value does not fit in shortening cast", R"SOURCE(
pub fn panic(message: []const u8) -> unreachable {
pub fn panic(message: []const u8) -> noreturn {
@breakpoint();
while (true) {}
}
@ -2009,7 +2009,7 @@ fn shorten_cast(x: i32) -> i8 {
)SOURCE");
add_debug_safety_case("signed integer not fitting in cast to unsigned integer", R"SOURCE(
pub fn panic(message: []const u8) -> unreachable {
pub fn panic(message: []const u8) -> noreturn {
@breakpoint();
while (true) {}
}
@ -2024,7 +2024,7 @@ fn unsigned_cast(x: i32) -> u32 {
)SOURCE");
add_debug_safety_case("unwrap error", R"SOURCE(
pub fn panic(message: []const u8) -> unreachable {
pub fn panic(message: []const u8) -> noreturn {
@breakpoint();
while (true) {}
}
@ -2055,7 +2055,7 @@ void baz(int8_t a, int16_t b, int32_t c, int64_t d);
add_parseh_case("noreturn attribute", AllowWarningsNo, R"SOURCE(
void foo(void) __attribute__((noreturn));
)SOURCE", 1, R"OUTPUT(pub extern fn foo() -> unreachable;)OUTPUT");
)SOURCE", 1, R"OUTPUT(pub extern fn foo() -> noreturn;)OUTPUT");
add_parseh_case("enums", AllowWarningsNo, R"SOURCE(
enum Foo {