authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-10-06 17:05:34+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-10-07 11:04:02+03:00
log29ae6515f3adc23df3d889acaf7ec62a2d01b707
treef774b68521f6aca221628201408e47b2b24f481a
parent11dce78944ecfab1838cd678f75c354aa376a8bf

AstGen: use 'shadows' instead of 'redeclaration' when names are in different scopes

Closes #8532

16 files changed, 72 insertions(+), 37 deletions(-)

doc/langref.html.in+1-1
......@@ -4064,7 +4064,7 @@ test "labeled break from labeled block expression" {
40644064
40654065 {#header_open|Shadowing#}
40664066 <p>{#link|Identifiers#} are never allowed to "hide" other identifiers by using the same name:</p>
4067 {#code_begin|test_err|local shadows declaration#}
4067 {#code_begin|test_err|local variable shadows declaration#}
40684068const pi = 3.14;
40694069
40704070test "inside test block" {
src/AstGen.zig+56-21
......@@ -2004,7 +2004,8 @@ fn blockExpr(
20042004 return labeledBlockExpr(gz, scope, rl, block_node, statements);
20052005 }
20062006
2007 try blockExprStmts(gz, scope, statements);
2007 var sub_gz = gz.makeSubBlock(scope);
2008 try blockExprStmts(&sub_gz, &sub_gz.base, statements);
20082009 return rvalue(gz, rl, .void_value, block_node);
20092010}
20102011
......@@ -2772,7 +2773,13 @@ fn varDecl(
27722773 }
27732774 const ident_name = try astgen.identAsString(name_token);
27742775
2775 try astgen.detectLocalShadowing(scope, ident_name, name_token, ident_name_raw);
2776 try astgen.detectLocalShadowing(
2777 scope,
2778 ident_name,
2779 name_token,
2780 ident_name_raw,
2781 if (token_tags[var_decl.ast.mut_token] == .keyword_const) .@"local constant" else .@"local variable",
2782 );
27762783
27772784 if (var_decl.ast.init_node == 0) {
27782785 return astgen.failNode(node, "variables must be initialized", .{});
......@@ -3502,7 +3509,7 @@ fn fnDecl(
35023509
35033510 const param_name = try astgen.identAsString(name_token);
35043511 if (!is_extern) {
3505 try astgen.detectLocalShadowing(params_scope, param_name, name_token, name_bytes);
3512 try astgen.detectLocalShadowing(params_scope, param_name, name_token, name_bytes, .@"function parameter");
35063513 }
35073514 break :blk param_name;
35083515 } else if (!is_extern) {
......@@ -5181,7 +5188,7 @@ fn orelseCatchExpr(
51815188 }
51825189 const err_name = try astgen.identAsString(payload);
51835190
5184 try astgen.detectLocalShadowing(scope, err_name, payload, err_str);
5191 try astgen.detectLocalShadowing(scope, err_name, payload, err_str, .@"capture");
51855192
51865193 err_val_scope = .{
51875194 .parent = &else_scope.base,
......@@ -5480,7 +5487,7 @@ fn ifExpr(
54805487 const token_name_str = tree.tokenSlice(token_name_index);
54815488 if (mem.eql(u8, "_", token_name_str))
54825489 break :s &then_scope.base;
5483 try astgen.detectLocalShadowing(&then_scope.base, ident_name, token_name_index, token_name_str);
5490 try astgen.detectLocalShadowing(&then_scope.base, ident_name, token_name_index, token_name_str, .@"capture");
54845491 payload_val_scope = .{
54855492 .parent = &then_scope.base,
54865493 .gen_zir = &then_scope,
......@@ -5505,7 +5512,7 @@ fn ifExpr(
55055512 break :s &then_scope.base;
55065513 const payload_inst = try then_scope.addUnNode(tag, cond.inst, if_full.ast.then_expr);
55075514 const ident_name = try astgen.identAsString(ident_token);
5508 try astgen.detectLocalShadowing(&then_scope.base, ident_name, ident_token, ident_bytes);
5515 try astgen.detectLocalShadowing(&then_scope.base, ident_name, ident_token, ident_bytes, .@"capture");
55095516 payload_val_scope = .{
55105517 .parent = &then_scope.base,
55115518 .gen_zir = &then_scope,
......@@ -5551,7 +5558,7 @@ fn ifExpr(
55515558 const error_token_str = tree.tokenSlice(error_token);
55525559 if (mem.eql(u8, "_", error_token_str))
55535560 break :s &else_scope.base;
5554 try astgen.detectLocalShadowing(&else_scope.base, ident_name, error_token, error_token_str);
5561 try astgen.detectLocalShadowing(&else_scope.base, ident_name, error_token, error_token_str, .@"capture");
55555562 payload_val_scope = .{
55565563 .parent = &else_scope.base,
55575564 .gen_zir = &else_scope,
......@@ -5816,7 +5823,7 @@ fn whileExpr(
58165823 break :s &then_scope.base;
58175824 const payload_name_loc = payload_token + @boolToInt(payload_is_ref);
58185825 const ident_name = try astgen.identAsString(payload_name_loc);
5819 try astgen.detectLocalShadowing(&then_scope.base, ident_name, payload_name_loc, ident_bytes);
5826 try astgen.detectLocalShadowing(&then_scope.base, ident_name, payload_name_loc, ident_bytes, .@"capture");
58205827 payload_val_scope = .{
58215828 .parent = &then_scope.base,
58225829 .gen_zir = &then_scope,
......@@ -5843,7 +5850,7 @@ fn whileExpr(
58435850 const ident_bytes = tree.tokenSlice(ident_token);
58445851 if (mem.eql(u8, "_", ident_bytes))
58455852 break :s &then_scope.base;
5846 try astgen.detectLocalShadowing(&then_scope.base, ident_name, ident_token, ident_bytes);
5853 try astgen.detectLocalShadowing(&then_scope.base, ident_name, ident_token, ident_bytes, .@"capture");
58475854 payload_val_scope = .{
58485855 .parent = &then_scope.base,
58495856 .gen_zir = &then_scope,
......@@ -5919,7 +5926,7 @@ fn whileExpr(
59195926 const ident_bytes = tree.tokenSlice(error_token);
59205927 if (mem.eql(u8, ident_bytes, "_"))
59215928 break :s &else_scope.base;
5922 try astgen.detectLocalShadowing(&else_scope.base, ident_name, error_token, ident_bytes);
5929 try astgen.detectLocalShadowing(&else_scope.base, ident_name, error_token, ident_bytes, .@"capture");
59235930 payload_val_scope = .{
59245931 .parent = &else_scope.base,
59255932 .gen_zir = &else_scope,
......@@ -6092,7 +6099,7 @@ fn forExpr(
60926099 .lhs = array_ptr,
60936100 .rhs = index,
60946101 });
6095 try astgen.detectLocalShadowing(&then_scope.base, name_str_index, ident, value_name);
6102 try astgen.detectLocalShadowing(&then_scope.base, name_str_index, ident, value_name, .@"capture");
60966103 payload_val_scope = .{
60976104 .parent = &then_scope.base,
60986105 .gen_zir = &then_scope,
......@@ -6118,7 +6125,7 @@ fn forExpr(
61186125 return astgen.failTok(index_token, "discard of index capture; omit it instead", .{});
61196126 }
61206127 const index_name = try astgen.identAsString(index_token);
6121 try astgen.detectLocalShadowing(payload_sub_scope, index_name, index_token, token_bytes);
6128 try astgen.detectLocalShadowing(payload_sub_scope, index_name, index_token, token_bytes, .@"loop index capture");
61226129 index_scope = .{
61236130 .parent = payload_sub_scope,
61246131 .gen_zir = &then_scope,
......@@ -6433,7 +6440,7 @@ fn switchExpr(
64336440 });
64346441 }
64356442 const capture_name = try astgen.identAsString(ident);
6436 try astgen.detectLocalShadowing(&case_scope.base, capture_name, ident, ident_slice);
6443 try astgen.detectLocalShadowing(&case_scope.base, capture_name, ident, ident_slice, .@"capture");
64376444 capture_val_scope = .{
64386445 .parent = &case_scope.base,
64396446 .gen_zir = &case_scope,
......@@ -6458,7 +6465,7 @@ fn switchExpr(
64586465 return astgen.failTok(tag_token, "tag capture on non-inline prong", .{});
64596466 }
64606467 const tag_name = try astgen.identAsString(tag_token);
6461 try astgen.detectLocalShadowing(payload_sub_scope, tag_name, tag_token, tag_slice);
6468 try astgen.detectLocalShadowing(payload_sub_scope, tag_name, tag_token, tag_slice, .@"switch tag capture");
64626469 tag_inst = @intCast(Zir.Inst.Index, astgen.instructions.len);
64636470 try astgen.instructions.append(gpa, .{
64646471 .tag = .switch_capture_tag,
......@@ -11669,6 +11676,7 @@ fn detectLocalShadowing(
1166911676 ident_name: u32,
1167011677 name_token: Ast.TokenIndex,
1167111678 token_bytes: []const u8,
11679 id_cat: Scope.IdCat,
1167211680) !void {
1167311681 const gpa = astgen.gpa;
1167411682 if (token_bytes[0] != '@' and isPrimitive(token_bytes)) {
......@@ -11682,6 +11690,7 @@ fn detectLocalShadowing(
1168211690 }
1168311691
1168411692 var s = scope;
11693 var outer_scope = false;
1168511694 while (true) switch (s.tag) {
1168611695 .local_val => {
1168711696 const local_val = s.cast(Scope.LocalVal).?;
......@@ -11689,6 +11698,17 @@ fn detectLocalShadowing(
1168911698 const name_slice = mem.span(astgen.nullTerminatedString(ident_name));
1169011699 const name = try gpa.dupe(u8, name_slice);
1169111700 defer gpa.free(name);
11701 if (outer_scope) {
11702 return astgen.failTokNotes(name_token, "{s} '{s}' shadows {s} from outer scope", .{
11703 @tagName(id_cat), name, @tagName(local_val.id_cat),
11704 }, &[_]u32{
11705 try astgen.errNoteTok(
11706 local_val.token_src,
11707 "previous declaration here",
11708 .{},
11709 ),
11710 });
11711 }
1169211712 return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{
1169311713 @tagName(local_val.id_cat), name,
1169411714 }, &[_]u32{
......@@ -11707,6 +11727,17 @@ fn detectLocalShadowing(
1170711727 const name_slice = mem.span(astgen.nullTerminatedString(ident_name));
1170811728 const name = try gpa.dupe(u8, name_slice);
1170911729 defer gpa.free(name);
11730 if (outer_scope) {
11731 return astgen.failTokNotes(name_token, "{s} '{s}' shadows {s} from outer scope", .{
11732 @tagName(id_cat), name, @tagName(local_ptr.id_cat),
11733 }, &[_]u32{
11734 try astgen.errNoteTok(
11735 local_ptr.token_src,
11736 "previous declaration here",
11737 .{},
11738 ),
11739 });
11740 }
1171011741 return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{
1171111742 @tagName(local_ptr.id_cat), name,
1171211743 }, &[_]u32{
......@@ -11720,6 +11751,7 @@ fn detectLocalShadowing(
1172011751 s = local_ptr.parent;
1172111752 },
1172211753 .namespace => {
11754 outer_scope = true;
1172311755 const ns = s.cast(Scope.Namespace).?;
1172411756 const decl_node = ns.decls.get(ident_name) orelse {
1172511757 s = ns.parent;
......@@ -11728,13 +11760,16 @@ fn detectLocalShadowing(
1172811760 const name_slice = mem.span(astgen.nullTerminatedString(ident_name));
1172911761 const name = try gpa.dupe(u8, name_slice);
1173011762 defer gpa.free(name);
11731 return astgen.failTokNotes(name_token, "local shadows declaration of '{s}'", .{
11732 name,
11763 return astgen.failTokNotes(name_token, "{s} shadows declaration of '{s}'", .{
11764 @tagName(id_cat), name,
1173311765 }, &[_]u32{
1173411766 try astgen.errNoteNode(decl_node, "declared here", .{}),
1173511767 });
1173611768 },
11737 .gen_zir => s = s.cast(GenZir).?.parent,
11769 .gen_zir => {
11770 s = s.cast(GenZir).?.parent;
11771 outer_scope = true;
11772 },
1173811773 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
1173911774 .top => break,
1174011775 };
......@@ -11844,8 +11879,8 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
1184411879 .local_val => {
1184511880 const local_val = s.cast(Scope.LocalVal).?;
1184611881 if (local_val.name == name_str_index) {
11847 return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{
11848 @tagName(local_val.id_cat), token_bytes,
11882 return astgen.failTokNotes(name_token, "declaration '{s}' shadows {s} from outer scope", .{
11883 token_bytes, @tagName(local_val.id_cat),
1184911884 }, &[_]u32{
1185011885 try astgen.errNoteTok(
1185111886 local_val.token_src,
......@@ -11859,8 +11894,8 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.
1185911894 .local_ptr => {
1186011895 const local_ptr = s.cast(Scope.LocalPtr).?;
1186111896 if (local_ptr.name == name_str_index) {
11862 return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{
11863 @tagName(local_ptr.id_cat), token_bytes,
11897 return astgen.failTokNotes(name_token, "declaration '{s}' shadows {s} from outer scope", .{
11898 token_bytes, @tagName(local_ptr.id_cat),
1186411899 }, &[_]u32{
1186511900 try astgen.errNoteTok(
1186611901 local_ptr.token_src,
test/cases/compile_errors/decl_shadows_local.zig+2-2
......@@ -16,7 +16,7 @@ fn bar(a: usize) void {
1616// backend=stage2
1717// target=native
1818//
19// :3:15: error: redeclaration of function parameter 'a'
19// :3:15: error: declaration 'a' shadows function parameter from outer scope
2020// :1:8: note: previous declaration here
21// :9:19: error: redeclaration of function parameter 'a'
21// :9:19: error: declaration 'a' shadows function parameter from outer scope
2222// :6:8: note: previous declaration here
test/cases/compile_errors/local_shadows_global_that_occurs_later.zig+1-1
......@@ -8,5 +8,5 @@ fn foo() void {}
88// backend=stage2
99// target=native
1010//
11// :2:9: error: local shadows declaration of 'foo'
11// :2:9: error: local variable shadows declaration of 'foo'
1212// :5:1: note: declared here
test/cases/compile_errors/local_variable_redeclares_parameter.zig+1-1
......@@ -7,5 +7,5 @@ export fn entry() void { f(1); }
77// backend=stage2
88// target=native
99//
10// :2:11: error: redeclaration of function parameter 'a'
10// :2:11: error: local constant 'a' shadows function parameter from outer scope
1111// :1:6: note: previous declaration here
test/cases/compile_errors/local_variable_shadowing_global.zig+1-1
......@@ -10,5 +10,5 @@ export fn entry() void {
1010// backend=stage2
1111// target=native
1212//
13// :5:9: error: local shadows declaration of 'Bar'
13// :5:9: error: local variable shadows declaration of 'Bar'
1414// :2:1: note: declared here
test/cases/compile_errors/parameter_shadowing_global.zig+1-1
......@@ -8,5 +8,5 @@ export fn entry() void {
88// backend=stage2
99// target=native
1010//
11// :2:6: error: local shadows declaration of 'Foo'
11// :2:6: error: function parameter shadows declaration of 'Foo'
1212// :1:1: note: declared here
test/cases/function_redeclaration.zig+1-1
......@@ -10,5 +10,5 @@ fn foo() void {
1010//
1111// :3:1: error: redeclaration of 'entry'
1212// :2:1: note: other declaration here
13// :6:9: error: local shadows declaration of 'foo'
13// :6:9: error: local variable shadows declaration of 'foo'
1414// :5:1: note: declared here
test/cases/variable_shadowing.1.zig+1-1
......@@ -5,5 +5,5 @@ pub fn main() void {
55
66// error
77//
8// :3:9: error: local shadows declaration of 'testing'
8// :3:9: error: local variable shadows declaration of 'testing'
99// :1:1: note: declared here
test/cases/variable_shadowing.3.zig+1-1
......@@ -6,5 +6,5 @@ pub fn main() void {
66
77// error
88//
9// :3:19: error: redeclaration of local variable 'i'
9// :3:19: error: loop index capture 'i' shadows local variable from outer scope
1010// :2:9: note: previous declaration here
test/cases/variable_shadowing.4.zig+1-1
......@@ -6,5 +6,5 @@ pub fn main() void {
66
77// error
88//
9// :3:16: error: redeclaration of local variable 'i'
9// :3:16: error: capture 'i' shadows local variable from outer scope
1010// :2:9: note: previous declaration here
test/cases/variable_shadowing.5.zig+1-1
......@@ -6,5 +6,5 @@ pub fn main() void {
66
77// error
88//
9// :3:18: error: redeclaration of local variable 'i'
9// :3:18: error: capture 'i' shadows local variable from outer scope
1010// :2:9: note: previous declaration here
test/cases/variable_shadowing.6.zig+1-1
......@@ -9,5 +9,5 @@ pub fn main() void {
99
1010// error
1111//
12// :5:13: error: redeclaration of local variable 'i'
12// :5:13: error: capture 'i' shadows local variable from outer scope
1313// :2:9: note: previous declaration here
test/cases/variable_shadowing.7.zig+1-1
......@@ -5,5 +5,5 @@ pub fn main() void {
55
66// error
77//
8// :3:16: error: redeclaration of local variable 'i'
8// :3:16: error: capture 'i' shadows local variable from outer scope
99// :2:9: note: previous declaration here
test/cases/variable_shadowing.8.zig+1-1
......@@ -5,5 +5,5 @@ pub fn main() void {
55
66// error
77//
8// :3:16: error: redeclaration of local variable 'i'
8// :3:16: error: capture 'i' shadows local variable from outer scope
99// :2:9: note: previous declaration here
test/cases/variable_shadowing.9.zig+1-1
......@@ -5,5 +5,5 @@ pub fn main() void {
55
66// error
77//
8// :3:28: error: redeclaration of local variable 'i'
8// :3:28: error: capture 'i' shadows local variable from outer scope
99// :2:9: note: previous declaration here