authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-28 17:29:56-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-28 17:29:56-07:00
log3f5ca3920a58d44a018ff2a2e277e60813e20d5a
treeff156147167ab13852411e5b2e9a6eed51ab88d0
parent54f774f7966e48a8419dbe2d3b37ae974ec03a83

AstGen: properly restore previous state after temporary changes

Before this, if a compile error occurred, it would cause the previous value for e.g. the function scope to not get reset. If the AstGen process continued, it would result in a violation of the data guarantees that it relies on. This commit takes advantage of defer to ensure the previous value is always reset, even in the case of an error. Closes #8920

2 files changed, 24 insertions(+), 14 deletions(-)

src/AstGen.zig+10-12
......@@ -249,9 +249,9 @@ pub const bool_rl: ResultLoc = .{ .ty = .bool_type };
249249fn typeExpr(gz: *GenZir, scope: *Scope, type_node: ast.Node.Index) InnerError!Zir.Inst.Ref {
250250 const prev_force_comptime = gz.force_comptime;
251251 gz.force_comptime = true;
252 const e = expr(gz, scope, .{ .ty = .type_type }, type_node);
253 gz.force_comptime = prev_force_comptime;
254 return e;
252 defer gz.force_comptime = prev_force_comptime;
253
254 return expr(gz, scope, .{ .ty = .type_type }, type_node);
255255}
256256
257257fn lvalExpr(gz: *GenZir, scope: *Scope, node: ast.Node.Index) InnerError!Zir.Inst.Ref {
......@@ -1465,9 +1465,9 @@ fn comptimeExpr(
14651465) InnerError!Zir.Inst.Ref {
14661466 const prev_force_comptime = gz.force_comptime;
14671467 gz.force_comptime = true;
1468 const result = try expr(gz, scope, rl, node);
1469 gz.force_comptime = prev_force_comptime;
1470 return result;
1468 defer gz.force_comptime = prev_force_comptime;
1469
1470 return expr(gz, scope, rl, node);
14711471}
14721472
14731473/// This one is for an actual `comptime` syntax, and will emit a compile error if
......@@ -2121,8 +2121,8 @@ fn genDefers(
21212121 const expr_node = node_datas[defer_scope.defer_node].rhs;
21222122 const prev_in_defer = gz.in_defer;
21232123 gz.in_defer = true;
2124 defer gz.in_defer = prev_in_defer;
21242125 try unusedResultExpr(gz, defer_scope.parent, expr_node);
2125 gz.in_defer = prev_in_defer;
21262126 },
21272127 .defer_error => {
21282128 const defer_scope = scope.cast(Scope.Defer).?;
......@@ -2131,8 +2131,8 @@ fn genDefers(
21312131 const expr_node = node_datas[defer_scope.defer_node].rhs;
21322132 const prev_in_defer = gz.in_defer;
21332133 gz.in_defer = true;
2134 defer gz.in_defer = prev_in_defer;
21342135 try unusedResultExpr(gz, defer_scope.parent, expr_node);
2135 gz.in_defer = prev_in_defer;
21362136 },
21372137 .namespace => unreachable,
21382138 .top => unreachable,
......@@ -2887,6 +2887,7 @@ fn fnDecl(
28872887
28882888 const prev_fn_block = astgen.fn_block;
28892889 astgen.fn_block = &fn_gz;
2890 defer astgen.fn_block = prev_fn_block;
28902891
28912892 // Iterate over the parameters. We put the param names as the first N
28922893 // items inside `extra` so that debug info later can refer to the parameter names
......@@ -2938,8 +2939,6 @@ fn fnDecl(
29382939 _ = try fn_gz.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node));
29392940 }
29402941
2941 astgen.fn_block = prev_fn_block;
2942
29432942 break :func try decl_gz.addFunc(.{
29442943 .src_node = decl_node,
29452944 .ret_ty = return_type_inst,
......@@ -3276,6 +3275,7 @@ fn testDecl(
32763275
32773276 const prev_fn_block = astgen.fn_block;
32783277 astgen.fn_block = &fn_block;
3278 defer astgen.fn_block = prev_fn_block;
32793279
32803280 const block_result = try expr(&fn_block, &fn_block.base, .none, body_node);
32813281 if (fn_block.instructions.items.len == 0 or !fn_block.refIsNoReturn(block_result)) {
......@@ -3284,8 +3284,6 @@ fn testDecl(
32843284 _ = try fn_block.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node));
32853285 }
32863286
3287 astgen.fn_block = prev_fn_block;
3288
32893287 const func_inst = try decl_block.addFunc(.{
32903288 .src_node = node,
32913289 .ret_ty = .void_type,
test/stage2/test.zig+14-2
......@@ -938,8 +938,7 @@ pub fn addCases(ctx: *TestContext) !void {
938938 \\pub fn b() !void {
939939 \\ defer return a();
940940 \\}
941
942 , &[_][]const u8{
941 , &[_][]const u8{
943942 ":7:8: error: try is not allowed inside defer expression",
944943 ":10:8: error: cannot return from defer expression",
945944 });
......@@ -979,6 +978,19 @@ pub fn addCases(ctx: *TestContext) !void {
979978 ":3:9: error: local shadows declaration of 'testing'",
980979 ":1:1: note: declared here",
981980 });
981 case.addError(
982 \\fn a() type {
983 \\ return struct {
984 \\ pub fn b() void {
985 \\ const c = 6;
986 \\ const c = 69;
987 \\ }
988 \\ };
989 \\}
990 , &[_][]const u8{
991 ":5:19: error: redeclaration of 'c'",
992 ":4:19: note: previously declared here",
993 });
982994 }
983995
984996 {