std: More type checks for Thread startFn return type

Closes #4756
master
LemonBoy 2020-03-18 09:35:44 +01:00 committed by Andrew Kelley
parent dbde5df568
commit 013ada1b59
1 changed files with 45 additions and 6 deletions

View File

@ -6,6 +6,8 @@ const windows = std.os.windows;
const c = std.c; const c = std.c;
const assert = std.debug.assert; const assert = std.debug.assert;
const bad_startfn_ret = "expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'";
pub const Thread = struct { pub const Thread = struct {
data: Data, data: Data,
@ -158,15 +160,34 @@ pub const Thread = struct {
}; };
fn threadMain(raw_arg: windows.LPVOID) callconv(.C) windows.DWORD { fn threadMain(raw_arg: windows.LPVOID) callconv(.C) windows.DWORD {
const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*; const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*;
switch (@typeInfo(@TypeOf(startFn).ReturnType)) { switch (@typeInfo(@TypeOf(startFn).ReturnType)) {
.Int => { .NoReturn => {
return startFn(arg); startFn(arg);
}, },
.Void => { .Void => {
startFn(arg); startFn(arg);
return 0; return 0;
}, },
else => @compileError("expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'"), .Int => |info| {
if (info.bits != 8) {
@compileError(bad_startfn_ret);
}
return startFn(arg);
},
.ErrorUnion => |info| {
if (info.payload != void) {
@compileError(bad_startfn_ret);
}
startFn(arg) catch |err| {
std.debug.warn("error: {}\n", .{@errorName(err)});
if (@errorReturnTrace()) |trace| {
std.debug.dumpStackTrace(trace.*);
}
};
return 0;
},
else => @compileError(bad_startfn_ret),
} }
} }
}; };
@ -202,14 +223,32 @@ pub const Thread = struct {
const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*; const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*;
switch (@typeInfo(@TypeOf(startFn).ReturnType)) { switch (@typeInfo(@TypeOf(startFn).ReturnType)) {
.Int => { .NoReturn => {
return startFn(arg); startFn(arg);
}, },
.Void => { .Void => {
startFn(arg); startFn(arg);
return 0; return 0;
}, },
else => @compileError("expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'"), .Int => |info| {
if (info.bits != 8) {
@compileError(bad_startfn_ret);
}
return startFn(arg);
},
.ErrorUnion => |info| {
if (info.payload != void) {
@compileError(bad_startfn_ret);
}
startFn(arg) catch |err| {
std.debug.warn("error: {}\n", .{@errorName(err)});
if (@errorReturnTrace()) |trace| {
std.debug.dumpStackTrace(trace.*);
}
};
return 0;
},
else => @compileError(bad_startfn_ret),
} }
} }
fn posixThreadMain(ctx: ?*c_void) callconv(.C) ?*c_void { fn posixThreadMain(ctx: ?*c_void) callconv(.C) ?*c_void {