authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-16 11:50:17-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-07-16 11:50:17-04:00
log9a9a7daef0aff340e029fb9bb6d29361a3d7e767
treeee3b87c09113bb012f9fd0b530ca77f5bcc2664e
parent0435026474cc3489337f3d6a7ac9d2e5cb1b7044
parent741c74e427a9502d7e074b2737016cc61bc29b44
signaturelock-open Commit is signed but in an unrecognized format.

Merge branch 'SamTebbs33-main-return'


5 files changed, 40 insertions(+), 13 deletions(-)

std/special/start.zig+21-11
......@@ -125,10 +125,13 @@ extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 {
125125 return callMainWithArgs(@intCast(usize, c_argc), c_argv, envp);
126126}
127127
128// General error message for a malformed return type
129const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'";
130
128131// This is marked inline because for some reason LLVM in release mode fails to inline it,
129132// and we want fewer call frames in stack traces.
130133inline fn callMain() u8 {
131 switch (@typeId(@typeOf(root.main).ReturnType)) {
134 switch (@typeInfo(@typeOf(root.main).ReturnType)) {
132135 .NoReturn => {
133136 root.main();
134137 },
......@@ -136,25 +139,32 @@ inline fn callMain() u8 {
136139 root.main();
137140 return 0;
138141 },
139 .Int => {
140 if (@typeOf(root.main).ReturnType.bit_count != 8) {
141 @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'");
142 .Int => |info| {
143 if (info.bits != 8) {
144 @compileError(bad_main_ret);
142145 }
143146 return root.main();
144147 },
145148 .ErrorUnion => {
146 root.main() catch |err| {
149 const result = root.main() catch |err| {
147150 std.debug.warn("error: {}\n", @errorName(err));
148 if (builtin.os != builtin.Os.zen) {
149 if (@errorReturnTrace()) |trace| {
150 std.debug.dumpStackTrace(trace.*);
151 }
151 if (@errorReturnTrace()) |trace| {
152 std.debug.dumpStackTrace(trace.*);
152153 }
153154 return 1;
154155 };
155 return 0;
156 switch (@typeInfo(@typeOf(result))) {
157 .Void => return 0,
158 .Int => |info| {
159 if (info.bits != 8) {
160 @compileError(bad_main_ret);
161 }
162 return result;
163 },
164 else => @compileError(bad_main_ret),
165 }
156166 },
157 else => @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'"),
167 else => @compileError(bad_main_ret),
158168 }
159169}
160170
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
......@@ -2247,7 +2247,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
22472247 "wrong return type for main",
22482248 \\pub fn main() f32 { }
22492249 ,
2250 "error: expected return type of main to be 'u8', 'noreturn', 'void', or '!void'",
2250 "error: expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'",
22512251 );
22522252
22532253 cases.add(
......@@ -2255,7 +2255,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
22552255 \\pub fn main() ??void {
22562256 \\}
22572257 ,
2258 "error: expected return type of main to be 'u8', 'noreturn', 'void', or '!void'",
2258 "error: expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'",
22592259 );
22602260
22612261 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}