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;...@@ -6,6 +6,8 @@ const windows = std.os.windows;
6const c = std.c;6const c = std.c;
7const assert = std.debug.assert;7const assert = std.debug.assert;
88
9const bad_startfn_ret = "expected return type of startFn to be 'u8', 'noreturn', 'void', or '!void'";
10
9pub const Thread = struct {11pub const Thread = struct {
10 data: Data,12 data: Data,
1113
...@@ -158,15 +160,34 @@ pub const Thread = struct {...@@ -158,15 +160,34 @@ pub const Thread = struct {
158 };160 };
159 fn threadMain(raw_arg: windows.LPVOID) callconv(.C) windows.DWORD {161 fn threadMain(raw_arg: windows.LPVOID) callconv(.C) windows.DWORD {
160 const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*;162 const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*;
163
161 switch (@typeInfo(@TypeOf(startFn).ReturnType)) {164 switch (@typeInfo(@TypeOf(startFn).ReturnType)) {
162 .Int => {165 .NoReturn => {
163 return startFn(arg);166 startFn(arg);
164 },167 },
165 .Void => {168 .Void => {
166 startFn(arg);169 startFn(arg);
167 return 0;170 return 0;
168 },171 },
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),
170 }191 }
171 }192 }
172 };193 };
...@@ -202,14 +223,32 @@ pub const Thread = struct {...@@ -202,14 +223,32 @@ pub const Thread = struct {
202 const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*;223 const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*;
203224
204 switch (@typeInfo(@TypeOf(startFn).ReturnType)) {225 switch (@typeInfo(@TypeOf(startFn).ReturnType)) {
205 .Int => {226 .NoReturn => {
206 return startFn(arg);227 startFn(arg);
207 },228 },
208 .Void => {229 .Void => {
209 startFn(arg);230 startFn(arg);
210 return 0;231 return 0;
211 },232 },
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),
213 }252 }
214 }253 }
215 fn posixThreadMain(ctx: ?*c_void) callconv(.C) ?*c_void {254 fn posixThreadMain(ctx: ?*c_void) callconv(.C) ?*c_void {