authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-26 16:20:38+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-07-29 10:08:35+03:00
log9e0a930ce3be01923602adbfee13b50842da08b7
treef48fa98efd8c6d75cf431fa3c10e231e3688d0ff
parentb5861193e072ba6780730a559f2b879378b8587f

stage2: add error for comptime control flow in runtime block


22 files changed, 173 insertions(+), 126 deletions(-)

src/AstGen.zig+4
......@@ -1940,6 +1940,9 @@ fn continueExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index)
19401940 .break_inline
19411941 else
19421942 .@"break";
1943 if (break_tag == .break_inline) {
1944 _ = try parent_gz.addNode(.check_comptime_control_flow, node);
1945 }
19431946 _ = try parent_gz.addBreak(break_tag, continue_block, .void_value);
19441947 return Zir.Inst.Ref.unreachable_value;
19451948 },
......@@ -2473,6 +2476,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: Ast.Node.Index) Inner
24732476 .repeat_inline,
24742477 .panic,
24752478 .panic_comptime,
2479 .check_comptime_control_flow,
24762480 => {
24772481 noreturn_src_node = statement;
24782482 break :b true;
src/Module.zig+2
......@@ -2283,6 +2283,8 @@ pub const SrcLoc = struct {
22832283 .@"while" => tree.whileFull(node).ast.cond_expr,
22842284 .for_simple => tree.forSimple(node).ast.cond_expr,
22852285 .@"for" => tree.forFull(node).ast.cond_expr,
2286 .@"orelse" => node,
2287 .@"catch" => node,
22862288 else => unreachable,
22872289 };
22882290 return nodeToSpan(tree, src_node);
src/Sema.zig+18
......@@ -1146,6 +1146,24 @@ fn analyzeBodyInner(
11461146 i += 1;
11471147 continue;
11481148 },
1149 .check_comptime_control_flow => {
1150 if (!block.is_comptime) {
1151 if (block.runtime_cond orelse block.runtime_loop) |runtime_src| {
1152 const inst_data = sema.code.instructions.items(.data)[inst].node;
1153 const src = LazySrcLoc.nodeOffset(inst_data);
1154 const msg = msg: {
1155 const msg = try sema.errMsg(block, src, "comptime control flow inside runtime block", .{});
1156 errdefer msg.destroy(sema.gpa);
1157
1158 try sema.errNote(block, runtime_src, msg, "runtime control flow here", .{});
1159 break :msg msg;
1160 };
1161 return sema.failWithOwnedErrorMsg(block, msg);
1162 }
1163 }
1164 i += 1;
1165 continue;
1166 },
11491167
11501168 // Special case instructions to handle comptime control flow.
11511169 .@"break" => {
src/Zir.zig+6
......@@ -280,6 +280,9 @@ pub const Inst = struct {
280280 /// break instruction in a block, and the target block is the parent.
281281 /// Uses the `break` union field.
282282 break_inline,
283 /// Checks that comptime control flow does not happen inside a runtime block.
284 /// Uses the `node` union field.
285 check_comptime_control_flow,
283286 /// Function call.
284287 /// Uses the `pl_node` union field with payload `Call`.
285288 /// AST node is the function call.
......@@ -1266,6 +1269,7 @@ pub const Inst = struct {
12661269 .repeat_inline,
12671270 .panic,
12681271 .panic_comptime,
1272 .check_comptime_control_flow,
12691273 => true,
12701274 };
12711275 }
......@@ -1315,6 +1319,7 @@ pub const Inst = struct {
13151319 .set_runtime_safety,
13161320 .memcpy,
13171321 .memset,
1322 .check_comptime_control_flow,
13181323 => true,
13191324
13201325 .param,
......@@ -1595,6 +1600,7 @@ pub const Inst = struct {
15951600 .bool_br_or = .bool_br,
15961601 .@"break" = .@"break",
15971602 .break_inline = .@"break",
1603 .check_comptime_control_flow = .node,
15981604 .call = .pl_node,
15991605 .cmp_lt = .pl_node,
16001606 .cmp_lte = .pl_node,
src/print_zir.zig+1
......@@ -409,6 +409,7 @@ const Writer = struct {
409409 .alloc_inferred_comptime_mut,
410410 .ret_ptr,
411411 .ret_type,
412 .check_comptime_control_flow,
412413 => try self.writeNode(stream, inst),
413414
414415 .error_value,
test/cases/compile_errors/comptime_continue_inside_runtime_catch.zig created+16
......@@ -0,0 +1,16 @@
1export fn entry() void {
2 const ints = [_]u8{ 1, 2 };
3 inline for (ints) |_| {
4 bad() catch continue;
5 }
6}
7fn bad() !void {
8 return error.Bad;
9}
10
11// error
12// backend=stage2
13// target=native
14//
15// :4:21: error: comptime control flow inside runtime block
16// :4:15: note: runtime control flow here
test/cases/compile_errors/comptime_continue_inside_runtime_if_bool.zig created+15
......@@ -0,0 +1,15 @@
1export fn entry() void {
2 var p: usize = undefined;
3 comptime var q = true;
4 inline while (q) {
5 if (p == 11) continue;
6 q = false;
7 }
8}
9
10// error
11// backend=stage2
12// target=native
13//
14// :5:22: error: comptime control flow inside runtime block
15// :5:15: note: runtime control flow here
test/cases/compile_errors/comptime_continue_inside_runtime_if_error.zig created+15
......@@ -0,0 +1,15 @@
1export fn entry() void {
2 var p: anyerror!i32 = undefined;
3 comptime var q = true;
4 inline while (q) {
5 if (p) |_| continue else |_| {}
6 q = false;
7 }
8}
9
10// error
11// backend=stage2
12// target=native
13//
14// :5:20: error: comptime control flow inside runtime block
15// :5:13: note: runtime control flow here
test/cases/compile_errors/comptime_continue_inside_runtime_if_optional.zig created+15
......@@ -0,0 +1,15 @@
1export fn entry() void {
2 var p: ?i32 = undefined;
3 comptime var q = true;
4 inline while (q) {
5 if (p) |_| continue;
6 q = false;
7 }
8}
9
10// error
11// backend=stage2
12// target=native
13//
14// :5:20: error: comptime control flow inside runtime block
15// :5:13: note: runtime control flow here
test/cases/compile_errors/comptime_continue_inside_runtime_orelse.zig created+16
......@@ -0,0 +1,16 @@
1export fn entry() void {
2 const ints = [_]u8{ 1, 2 };
3 inline for (ints) |_| {
4 bad() orelse continue;
5 }
6}
7fn bad() ?void {
8 return null;
9}
10
11// error
12// backend=stage2
13// target=native
14//
15// :4:22: error: comptime control flow inside runtime block
16// :4:15: note: runtime control flow here
test/cases/compile_errors/comptime_continue_inside_runtime_switch.zig created+18
......@@ -0,0 +1,18 @@
1export fn entry() void {
2 var p: i32 = undefined;
3 comptime var q = true;
4 inline while (q) {
5 switch (p) {
6 11 => continue,
7 else => {},
8 }
9 q = false;
10 }
11}
12
13// error
14// backend=stage2
15// target=native
16//
17// :6:19: error: comptime control flow inside runtime block
18// :5:17: note: runtime control flow here
test/cases/compile_errors/comptime_continue_inside_runtime_while_bool.zig created+15
......@@ -0,0 +1,15 @@
1export fn entry() void {
2 var p: usize = undefined;
3 comptime var q = true;
4 outer: inline while (q) {
5 while (p == 11) continue :outer;
6 q = false;
7 }
8}
9
10// error
11// backend=stage2
12// target=native
13//
14// :5:25: error: comptime control flow inside runtime block
15// :5:18: note: runtime control flow here
test/cases/compile_errors/comptime_continue_inside_runtime_while_error.zig created+17
......@@ -0,0 +1,17 @@
1export fn entry() void {
2 var p: anyerror!usize = undefined;
3 comptime var q = true;
4 outer: inline while (q) {
5 while (p) |_| {
6 continue :outer;
7 } else |_| {}
8 q = false;
9 }
10}
11
12// error
13// backend=stage2
14// target=native
15//
16// :6:13: error: comptime control flow inside runtime block
17// :5:16: note: runtime control flow here
test/cases/compile_errors/comptime_continue_inside_runtime_while_optional.zig created+15
......@@ -0,0 +1,15 @@
1export fn entry() void {
2 var p: ?usize = undefined;
3 comptime var q = true;
4 outer: inline while (q) {
5 while (p) |_| continue :outer;
6 q = false;
7 }
8}
9
10// error
11// backend=stage2
12// target=native
13//
14// :5:23: error: comptime control flow inside runtime block
15// :5:16: note: runtime control flow here
test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_catch.zig deleted-16
......@@ -1,16 +0,0 @@
1export fn entry() void {
2 const ints = [_]u8{ 1, 2 };
3 inline for (ints) |_| {
4 bad() catch continue;
5 }
6}
7fn bad() !void {
8 return error.Bad;
9}
10
11// error
12// backend=stage1
13// target=native
14//
15// tmp.zig:4:21: error: comptime control flow inside runtime block
16// tmp.zig:4:15: note: runtime block created here
test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_bool.zig deleted-15
......@@ -1,15 +0,0 @@
1export fn entry() void {
2 var p: usize = undefined;
3 comptime var q = true;
4 inline while (q) {
5 if (p == 11) continue;
6 q = false;
7 }
8}
9
10// error
11// backend=stage1
12// target=native
13//
14// tmp.zig:5:22: error: comptime control flow inside runtime block
15// tmp.zig:5:9: note: runtime block created here
test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_error.zig deleted-15
......@@ -1,15 +0,0 @@
1export fn entry() void {
2 var p: anyerror!i32 = undefined;
3 comptime var q = true;
4 inline while (q) {
5 if (p) |_| continue else |_| {}
6 q = false;
7 }
8}
9
10// error
11// backend=stage1
12// target=native
13//
14// tmp.zig:5:20: error: comptime control flow inside runtime block
15// tmp.zig:5:9: note: runtime block created here
test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_if_optional.zig deleted-15
......@@ -1,15 +0,0 @@
1export fn entry() void {
2 var p: ?i32 = undefined;
3 comptime var q = true;
4 inline while (q) {
5 if (p) |_| continue;
6 q = false;
7 }
8}
9
10// error
11// backend=stage1
12// target=native
13//
14// tmp.zig:5:20: error: comptime control flow inside runtime block
15// tmp.zig:5:9: note: runtime block created here
test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_switch.zig deleted-18
......@@ -1,18 +0,0 @@
1export fn entry() void {
2 var p: i32 = undefined;
3 comptime var q = true;
4 inline while (q) {
5 switch (p) {
6 11 => continue,
7 else => {},
8 }
9 q = false;
10 }
11}
12
13// error
14// backend=stage1
15// target=native
16//
17// tmp.zig:6:19: error: comptime control flow inside runtime block
18// tmp.zig:5:9: note: runtime block created here
test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_bool.zig deleted-15
......@@ -1,15 +0,0 @@
1export fn entry() void {
2 var p: usize = undefined;
3 comptime var q = true;
4 outer: inline while (q) {
5 while (p == 11) continue :outer;
6 q = false;
7 }
8}
9
10// error
11// backend=stage1
12// target=native
13//
14// tmp.zig:5:25: error: comptime control flow inside runtime block
15// tmp.zig:5:9: note: runtime block created here
test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_error.zig deleted-17
......@@ -1,17 +0,0 @@
1export fn entry() void {
2 var p: anyerror!usize = undefined;
3 comptime var q = true;
4 outer: inline while (q) {
5 while (p) |_| {
6 continue :outer;
7 } else |_| {}
8 q = false;
9 }
10}
11
12// error
13// backend=stage1
14// target=native
15//
16// tmp.zig:6:13: error: comptime control flow inside runtime block
17// tmp.zig:5:9: note: runtime block created here
test/cases/compile_errors/stage1/obj/comptime_continue_inside_runtime_while_optional.zig deleted-15
......@@ -1,15 +0,0 @@
1export fn entry() void {
2 var p: ?usize = undefined;
3 comptime var q = true;
4 outer: inline while (q) {
5 while (p) |_| continue :outer;
6 q = false;
7 }
8}
9
10// error
11// backend=stage1
12// target=native
13//
14// tmp.zig:5:23: error: comptime control flow inside runtime block
15// tmp.zig:5:9: note: runtime block created here