| author | |
| committer | |
| log | f24b8f2a4a8ffc014231e6f294153ff05be16f38 |
| tree | 9486ed7172dc0c8c553551e12e509517d4a56643 |
| parent | 57d6724186ead79ac76491f42390c0d581a76b04 |
5 files changed, 41 insertions(+), 14 deletions(-)
std/special/start.zig+22-12| ... | @@ -121,6 +121,9 @@ extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 { | ... | @@ -121,6 +121,9 @@ extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 { |
| 121 | // This is marked inline because for some reason LLVM in release mode fails to inline it, | 121 | // This is marked inline because for some reason LLVM in release mode fails to inline it, |
| 122 | // and we want fewer call frames in stack traces. | 122 | // and we want fewer call frames in stack traces. |
| 123 | inline fn callMain() u8 { | 123 | inline fn callMain() u8 { |
| 124 | // General error message for a malformed return type | ||
| 125 | const compile_err_prefix = "expected return type of main to be 'u8', 'noreturn', 'void', '!void', or '!u8', found '"; | ||
| 126 | const compile_err = compile_err_prefix ++ @typeName(@typeOf(root.main).ReturnType) ++ "'"; | ||
| 124 | switch (@typeId(@typeOf(root.main).ReturnType)) { | 127 | switch (@typeId(@typeOf(root.main).ReturnType)) { |
| 125 | .NoReturn => { | 128 | .NoReturn => { |
| 126 | root.main(); | 129 | root.main(); |
| ... | @@ -131,23 +134,30 @@ inline fn callMain() u8 { | ... | @@ -131,23 +134,30 @@ inline fn callMain() u8 { |
| 131 | }, | 134 | }, |
| 132 | .Int => { | 135 | .Int => { |
| 133 | if (@typeOf(root.main).ReturnType.bit_count != 8) { | 136 | if (@typeOf(root.main).ReturnType.bit_count != 8) { |
| 134 | @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'"); | 137 | @compileError(compile_err); |
| 135 | } | 138 | } |
| 136 | return root.main(); | 139 | return root.main(); |
| 137 | }, | 140 | }, |
| 138 | .ErrorUnion => { | 141 | builtin.TypeId.ErrorUnion => { |
| 139 | root.main() catch |err| { | 142 | const PayloadType = @typeOf(root.main).ReturnType.Payload; |
| 140 | std.debug.warn("error: {}\n", @errorName(err)); | 143 | // In this case the error should include the payload type |
| 141 | if (builtin.os != builtin.Os.zen) { | 144 | const payload_err = compile_err_prefix ++ "!" ++ @typeName(PayloadType) ++ "'"; |
| 142 | if (@errorReturnTrace()) |trace| { | 145 | // If the payload is void or a u8 |
| 143 | std.debug.dumpStackTrace(trace.*); | 146 | if (@typeId(PayloadType) == builtin.TypeId.Void or (@typeId(PayloadType) == builtin.TypeId.Int and PayloadType.bit_count == 8)) { |
| 147 | const tmp = root.main() catch |err| { | ||
| 148 | std.debug.warn("error: {}\n", @errorName(err)); | ||
| 149 | if (builtin.os != builtin.Os.zen) { | ||
| 150 | if (@errorReturnTrace()) |trace| { | ||
| 151 | std.debug.dumpStackTrace(trace.*); | ||
| 152 | } | ||
| 144 | } | 153 | } |
| 145 | } | 154 | return 1; |
| 146 | return 1; | 155 | }; |
| 147 | }; | 156 | // If main didn't error, return 0 or the exit code |
| 148 | return 0; | 157 | return if (PayloadType == void) 0 else tmp; |
| 158 | } else @compileError(payload_err); | ||
| 149 | }, | 159 | }, |
| 150 | else => @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'"), | 160 | else => @compileError(compile_err), |
| 151 | } | 161 | } |
| 152 | } | 162 | } |
| 153 | 163 |
test/build_examples.zig+2| ... | @@ -7,6 +7,8 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void { | ... | @@ -7,6 +7,8 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void { |
| 7 | cases.addC("example/hello_world/hello_libc.zig"); | 7 | cases.addC("example/hello_world/hello_libc.zig"); |
| 8 | cases.add("example/cat/main.zig"); | 8 | cases.add("example/cat/main.zig"); |
| 9 | cases.add("example/guess_number/main.zig"); | 9 | cases.add("example/guess_number/main.zig"); |
| 10 | cases.add("test/standalone/main_return_error/error_u8.zig"); | ||
| 11 | cases.add("test/standalone/main_return_error/error_u8_non_zero.zig"); | ||
| 10 | cases.addBuildFile("test/standalone/main_pkg_path/build.zig"); | 12 | cases.addBuildFile("test/standalone/main_pkg_path/build.zig"); |
| 11 | cases.addBuildFile("example/shared_library/build.zig"); | 13 | cases.addBuildFile("example/shared_library/build.zig"); |
| 12 | cases.addBuildFile("example/mix_o_files/build.zig"); | 14 | cases.addBuildFile("example/mix_o_files/build.zig"); |
test/compile_errors.zig+2-2| ... | @@ -2213,7 +2213,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2213,7 +2213,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2213 | "wrong return type for main", | 2213 | "wrong return type for main", |
| 2214 | \\pub fn main() f32 { } | 2214 | \\pub fn main() f32 { } |
| 2215 | , | 2215 | , |
| 2216 | "error: expected return type of main to be 'u8', 'noreturn', 'void', or '!void'", | 2216 | "error: expected return type of main to be 'u8', 'noreturn', 'void', '!void', or '!u8'", |
| 2217 | ); | 2217 | ); |
| 2218 | 2218 | ||
| 2219 | cases.add( | 2219 | cases.add( |
| ... | @@ -2221,7 +2221,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -2221,7 +2221,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 2221 | \\pub fn main() ??void { | 2221 | \\pub fn main() ??void { |
| 2222 | \\} | 2222 | \\} |
| 2223 | , | 2223 | , |
| 2224 | "error: expected return type of main to be 'u8', 'noreturn', 'void', or '!void'", | 2224 | "error: expected return type of main to be 'u8', 'noreturn', 'void', '!void', or '!u8'", |
| 2225 | ); | 2225 | ); |
| 2226 | 2226 | ||
| 2227 | cases.add( | 2227 | cases.add( |
test/standalone/main_return_error/error_u8.zig created+7| ... | @@ -0,0 +1,7 @@ | ||
| 1 | const Err = error { | ||
| 2 | Foo | ||
| 3 | }; | ||
| 4 | |||
| 5 | pub fn main() !u8 { | ||
| 6 | return Err.Foo; | ||
| 7 | } | ||
test/standalone/main_return_error/error_u8_non_zero.zig created+8| ... | @@ -0,0 +1,8 @@ | ||
| 1 | const Err = error { Foo }; | ||
| 2 | |||
| 3 | fn foo() u8 { var x = @intCast(u8, 9); return x; } | ||
| 4 | |||
| 5 | pub fn main() !u8 { | ||
| 6 | if (foo() == 7) return Err.Foo; | ||
| 7 | return 123; | ||
| 8 | } | ||