authorgravatar for samuel.tebbs@gmail.comSamTebbs33 <samuel.tebbs@gmail.com> 2019-06-21 00:29:47+01:00
committergravatar for sam.tebbs@arm.comSam Tebbs <sam.tebbs@arm.com> 2019-07-04 14:26:05+01:00
logf24b8f2a4a8ffc014231e6f294153ff05be16f38
tree9486ed7172dc0c8c553551e12e509517d4a56643
parent57d6724186ead79ac76491f42390c0d581a76b04

Support returning !u8 from main


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 {
121121// This is marked inline because for some reason LLVM in release mode fails to inline it,
122122// and we want fewer call frames in stack traces.
123123inline 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) ++ "'";
124127 switch (@typeId(@typeOf(root.main).ReturnType)) {
125128 .NoReturn => {
126129 root.main();
......@@ -131,23 +134,30 @@ inline fn callMain() u8 {
131134 },
132135 .Int => {
133136 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);
135138 }
136139 return root.main();
137140 },
138 .ErrorUnion => {
139 root.main() catch |err| {
140 std.debug.warn("error: {}\n", @errorName(err));
141 if (builtin.os != builtin.Os.zen) {
142 if (@errorReturnTrace()) |trace| {
143 std.debug.dumpStackTrace(trace.*);
141 builtin.TypeId.ErrorUnion => {
142 const PayloadType = @typeOf(root.main).ReturnType.Payload;
143 // In this case the error should include the payload type
144 const payload_err = compile_err_prefix ++ "!" ++ @typeName(PayloadType) ++ "'";
145 // If the payload is void or a u8
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 }
144153 }
145 }
146 return 1;
147 };
148 return 0;
154 return 1;
155 };
156 // If main didn't error, return 0 or the exit code
157 return if (PayloadType == void) 0 else tmp;
158 } else @compileError(payload_err);
149159 },
150 else => @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'"),
160 else => @compileError(compile_err),
151161 }
152162}
153163
test/build_examples.zig+2
......@@ -7,6 +7,8 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void {
77 cases.addC("example/hello_world/hello_libc.zig");
88 cases.add("example/cat/main.zig");
99 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");
1012 cases.addBuildFile("test/standalone/main_pkg_path/build.zig");
1113 cases.addBuildFile("example/shared_library/build.zig");
1214 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 {
22132213 "wrong return type for main",
22142214 \\pub fn main() f32 { }
22152215 ,
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'",
22172217 );
22182218
22192219 cases.add(
......@@ -2221,7 +2221,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
22212221 \\pub fn main() ??void {
22222222 \\}
22232223 ,
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'",
22252225 );
22262226
22272227 cases.add(
test/standalone/main_return_error/error_u8.zig created+7
......@@ -0,0 +1,7 @@
1const Err = error {
2 Foo
3};
4
5pub fn main() !u8 {
6 return Err.Foo;
7}
test/standalone/main_return_error/error_u8_non_zero.zig created+8
......@@ -0,0 +1,8 @@
1const Err = error { Foo };
2
3fn foo() u8 { var x = @intCast(u8, 9); return x; }
4
5pub fn main() !u8 {
6 if (foo() == 7) return Err.Foo;
7 return 123;
8}