authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-03-18 09:35:44+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-03-18 10:37:35-04:00
log013ada1b59e50bbbab19acab0a79dae72133999a
treee226bd24b51af23d4924c53f17041caca3bdb16b
parentdbde5df568597c63e28bb1244d695156afbad5d0

std: More type checks for Thread startFn return type

Closes #4756

1 files changed, 45 insertions(+), 6 deletions(-)

lib/std/thread.zig+45-6
......@@ -6,6 +6,8 @@ const windows = std.os.windows;
66const c = std.c;
77const assert = std.debug.assert;
88
9const bad_startfn_ret = "expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'";
10
911pub const Thread = struct {
1012 data: Data,
1113
......@@ -158,15 +160,34 @@ pub const Thread = struct {
158160 };
159161 fn threadMain(raw_arg: windows.LPVOID) callconv(.C) windows.DWORD {
160162 const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*;
163
161164 switch (@typeInfo(@TypeOf(startFn).ReturnType)) {
162 .Int => {
163 return startFn(arg);
165 .NoReturn => {
166 startFn(arg);
164167 },
165168 .Void => {
166169 startFn(arg);
167170 return 0;
168171 },
169 else => @compileError("expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'"),
172 .Int => |info| {
173 if (info.bits != 8) {
174 @compileError(bad_startfn_ret);
175 }
176 return startFn(arg);
177 },
178 .ErrorUnion => |info| {
179 if (info.payload != void) {
180 @compileError(bad_startfn_ret);
181 }
182 startFn(arg) catch |err| {
183 std.debug.warn("error: {}\n", .{@errorName(err)});
184 if (@errorReturnTrace()) |trace| {
185 std.debug.dumpStackTrace(trace.*);
186 }
187 };
188 return 0;
189 },
190 else => @compileError(bad_startfn_ret),
170191 }
171192 }
172193 };
......@@ -202,14 +223,32 @@ pub const Thread = struct {
202223 const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*;
203224
204225 switch (@typeInfo(@TypeOf(startFn).ReturnType)) {
205 .Int => {
206 return startFn(arg);
226 .NoReturn => {
227 startFn(arg);
207228 },
208229 .Void => {
209230 startFn(arg);
210231 return 0;
211232 },
212 else => @compileError("expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'"),
233 .Int => |info| {
234 if (info.bits != 8) {
235 @compileError(bad_startfn_ret);
236 }
237 return startFn(arg);
238 },
239 .ErrorUnion => |info| {
240 if (info.payload != void) {
241 @compileError(bad_startfn_ret);
242 }
243 startFn(arg) catch |err| {
244 std.debug.warn("error: {}\n", .{@errorName(err)});
245 if (@errorReturnTrace()) |trace| {
246 std.debug.dumpStackTrace(trace.*);
247 }
248 };
249 return 0;
250 },
251 else => @compileError(bad_startfn_ret),
213252 }
214253 }
215254 fn posixThreadMain(ctx: ?*c_void) callconv(.C) ?*c_void {