authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-16 11:27:11-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-16 11:27:11-04:00
log45cc488cef0ffed3d3471433300c3252f6ddfe2a
tree79057d089ea4357496cd56dc487759de7d55f822
parent0435026474cc3489337f3d6a7ac9d2e5cb1b7044
parentf24b8f2a4a8ffc014231e6f294153ff05be16f38
signature Commit is signed but in an unrecognized format.

Merge branch 'main-return-!u8' of https://github.com/SamTebbs33/zig into SamTebbs33-main-return


5 files changed, 41 insertions(+), 14 deletions(-)

std/special/start.zig+22-12
...@@ -128,6 +128,9 @@ extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 {...@@ -128,6 +128,9 @@ extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 {
128// This is marked inline because for some reason LLVM in release mode fails to inline it,128// This is marked inline because for some reason LLVM in release mode fails to inline it,
129// and we want fewer call frames in stack traces.129// and we want fewer call frames in stack traces.
130inline fn callMain() u8 {130inline fn callMain() u8 {
131 // General error message for a malformed return type
132 const compile_err_prefix = "expected return type of main to be 'u8', 'noreturn', 'void', '!void', or '!u8', found '";
133 const compile_err = compile_err_prefix ++ @typeName(@typeOf(root.main).ReturnType) ++ "'";
131 switch (@typeId(@typeOf(root.main).ReturnType)) {134 switch (@typeId(@typeOf(root.main).ReturnType)) {
132 .NoReturn => {135 .NoReturn => {
133 root.main();136 root.main();
...@@ -138,23 +141,30 @@ inline fn callMain() u8 {...@@ -138,23 +141,30 @@ inline fn callMain() u8 {
138 },141 },
139 .Int => {142 .Int => {
140 if (@typeOf(root.main).ReturnType.bit_count != 8) {143 if (@typeOf(root.main).ReturnType.bit_count != 8) {
141 @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'");144 @compileError(compile_err);
142 }145 }
143 return root.main();146 return root.main();
144 },147 },
145 .ErrorUnion => {148 builtin.TypeId.ErrorUnion => {
146 root.main() catch |err| {149 const PayloadType = @typeOf(root.main).ReturnType.Payload;
147 std.debug.warn("error: {}\n", @errorName(err));150 // In this case the error should include the payload type
148 if (builtin.os != builtin.Os.zen) {151 const payload_err = compile_err_prefix ++ "!" ++ @typeName(PayloadType) ++ "'";
149 if (@errorReturnTrace()) |trace| {152 // If the payload is void or a u8
150 std.debug.dumpStackTrace(trace.*);153 if (@typeId(PayloadType) == builtin.TypeId.Void or (@typeId(PayloadType) == builtin.TypeId.Int and PayloadType.bit_count == 8)) {
154 const tmp = root.main() catch |err| {
155 std.debug.warn("error: {}\n", @errorName(err));
156 if (builtin.os != builtin.Os.zen) {
157 if (@errorReturnTrace()) |trace| {
158 std.debug.dumpStackTrace(trace.*);
159 }
151 }160 }
152 }161 return 1;
153 return 1;162 };
154 };163 // If main didn't error, return 0 or the exit code
155 return 0;164 return if (PayloadType == void) 0 else tmp;
165 } else @compileError(payload_err);
156 },166 },
157 else => @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'"),167 else => @compileError(compile_err),
158 }168 }
159}169}
160170
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
...@@ -2247,7 +2247,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2247,7 +2247,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2247 "wrong return type for main",2247 "wrong return type for main",
2248 \\pub fn main() f32 { }2248 \\pub fn main() f32 { }
2249 ,2249 ,
2250 "error: expected return type of main to be 'u8', 'noreturn', 'void', or '!void'",2250 "error: expected return type of main to be 'u8', 'noreturn', 'void', '!void', or '!u8'",
2251 );2251 );
22522252
2253 cases.add(2253 cases.add(
...@@ -2255,7 +2255,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2255,7 +2255,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2255 \\pub fn main() ??void {2255 \\pub fn main() ??void {
2256 \\}2256 \\}
2257 ,2257 ,
2258 "error: expected return type of main to be 'u8', 'noreturn', 'void', or '!void'",2258 "error: expected return type of main to be 'u8', 'noreturn', 'void', '!void', or '!u8'",
2259 );2259 );
22602260
2261 cases.add(2261 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}