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

master
Andrew Kelley 2019-07-16 11:27:11 -04:00
commit 45cc488cef
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
5 changed files with 41 additions and 14 deletions

View File

@ -128,6 +128,9 @@ extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 {
// This is marked inline because for some reason LLVM in release mode fails to inline it,
// and we want fewer call frames in stack traces.
inline fn callMain() u8 {
// General error message for a malformed return type
const compile_err_prefix = "expected return type of main to be 'u8', 'noreturn', 'void', '!void', or '!u8', found '";
const compile_err = compile_err_prefix ++ @typeName(@typeOf(root.main).ReturnType) ++ "'";
switch (@typeId(@typeOf(root.main).ReturnType)) {
.NoReturn => {
root.main();
@ -138,23 +141,30 @@ inline fn callMain() u8 {
},
.Int => {
if (@typeOf(root.main).ReturnType.bit_count != 8) {
@compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'");
@compileError(compile_err);
}
return root.main();
},
.ErrorUnion => {
root.main() catch |err| {
std.debug.warn("error: {}\n", @errorName(err));
if (builtin.os != builtin.Os.zen) {
if (@errorReturnTrace()) |trace| {
std.debug.dumpStackTrace(trace.*);
builtin.TypeId.ErrorUnion => {
const PayloadType = @typeOf(root.main).ReturnType.Payload;
// In this case the error should include the payload type
const payload_err = compile_err_prefix ++ "!" ++ @typeName(PayloadType) ++ "'";
// If the payload is void or a u8
if (@typeId(PayloadType) == builtin.TypeId.Void or (@typeId(PayloadType) == builtin.TypeId.Int and PayloadType.bit_count == 8)) {
const tmp = root.main() catch |err| {
std.debug.warn("error: {}\n", @errorName(err));
if (builtin.os != builtin.Os.zen) {
if (@errorReturnTrace()) |trace| {
std.debug.dumpStackTrace(trace.*);
}
}
}
return 1;
};
return 0;
return 1;
};
// If main didn't error, return 0 or the exit code
return if (PayloadType == void) 0 else tmp;
} else @compileError(payload_err);
},
else => @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'"),
else => @compileError(compile_err),
}
}

View File

@ -7,6 +7,8 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void {
cases.addC("example/hello_world/hello_libc.zig");
cases.add("example/cat/main.zig");
cases.add("example/guess_number/main.zig");
cases.add("test/standalone/main_return_error/error_u8.zig");
cases.add("test/standalone/main_return_error/error_u8_non_zero.zig");
cases.addBuildFile("test/standalone/main_pkg_path/build.zig");
cases.addBuildFile("example/shared_library/build.zig");
cases.addBuildFile("example/mix_o_files/build.zig");

View File

@ -2247,7 +2247,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"wrong return type for main",
\\pub fn main() f32 { }
,
"error: expected return type of main to be 'u8', 'noreturn', 'void', or '!void'",
"error: expected return type of main to be 'u8', 'noreturn', 'void', '!void', or '!u8'",
);
cases.add(
@ -2255,7 +2255,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
\\pub fn main() ??void {
\\}
,
"error: expected return type of main to be 'u8', 'noreturn', 'void', or '!void'",
"error: expected return type of main to be 'u8', 'noreturn', 'void', '!void', or '!u8'",
);
cases.add(

View File

@ -0,0 +1,7 @@
const Err = error {
Foo
};
pub fn main() !u8 {
return Err.Foo;
}

View File

@ -0,0 +1,8 @@
const Err = error { Foo };
fn foo() u8 { var x = @intCast(u8, 9); return x; }
pub fn main() !u8 {
if (foo() == 7) return Err.Foo;
return 123;
}