authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-28 10:17:47-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-28 13:28:34-04:00
log6a6e2cd64f3ebb1919dd0ac53d8a1f29c56e6ec2
tree9d698bc9013ee12ba43c83483d2cac4b63b26d7a
parentf30aa25cbf9c9a415963b4ea69d7efa09237a704

AstGen: allow locals with same name as primitives with `@""` syntax

This makes local names follow the same rule as declaration names.

3 files changed, 41 insertions(+), 29 deletions(-)

src/AstGen.zig+35-22
...@@ -2385,7 +2385,7 @@ fn varDecl(...@@ -2385,7 +2385,7 @@ fn varDecl(
2385 }2385 }
2386 const ident_name = try astgen.identAsString(name_token);2386 const ident_name = try astgen.identAsString(name_token);
23872387
2388 try astgen.detectLocalShadowing(scope, ident_name, name_token);2388 try astgen.detectLocalShadowing(scope, ident_name, name_token, ident_name_raw);
23892389
2390 if (var_decl.ast.init_node == 0) {2390 if (var_decl.ast.init_node == 0) {
2391 return astgen.failNode(node, "variables must be initialized", .{});2391 return astgen.failNode(node, "variables must be initialized", .{});
...@@ -2952,12 +2952,13 @@ fn fnDecl(...@@ -2952,12 +2952,13 @@ fn fnDecl(
2952 } else false;2952 } else false;
29532953
2954 const param_name: u32 = if (param.name_token) |name_token| blk: {2954 const param_name: u32 = if (param.name_token) |name_token| blk: {
2955 if (mem.eql(u8, "_", tree.tokenSlice(name_token)))2955 const name_bytes = tree.tokenSlice(name_token);
2956 if (mem.eql(u8, "_", name_bytes))
2956 break :blk 0;2957 break :blk 0;
29572958
2958 const param_name = try astgen.identAsString(name_token);2959 const param_name = try astgen.identAsString(name_token);
2959 if (!is_extern) {2960 if (!is_extern) {
2960 try astgen.detectLocalShadowing(params_scope, param_name, name_token);2961 try astgen.detectLocalShadowing(params_scope, param_name, name_token, name_bytes);
2961 }2962 }
2962 break :blk param_name;2963 break :blk param_name;
2963 } else if (!is_extern) {2964 } else if (!is_extern) {
...@@ -5035,7 +5036,7 @@ fn ifExpr(...@@ -5035,7 +5036,7 @@ fn ifExpr(
5035 const token_name_str = tree.tokenSlice(token_name_index);5036 const token_name_str = tree.tokenSlice(token_name_index);
5036 if (mem.eql(u8, "_", token_name_str))5037 if (mem.eql(u8, "_", token_name_str))
5037 break :s &then_scope.base;5038 break :s &then_scope.base;
5038 try astgen.detectLocalShadowing(&then_scope.base, ident_name, token_name_index);5039 try astgen.detectLocalShadowing(&then_scope.base, ident_name, token_name_index, token_name_str);
5039 payload_val_scope = .{5040 payload_val_scope = .{
5040 .parent = &then_scope.base,5041 .parent = &then_scope.base,
5041 .gen_zir = &then_scope,5042 .gen_zir = &then_scope,
...@@ -5054,11 +5055,12 @@ fn ifExpr(...@@ -5054,11 +5055,12 @@ fn ifExpr(
5054 .optional_payload_unsafe_ptr5055 .optional_payload_unsafe_ptr
5055 else5056 else
5056 .optional_payload_unsafe;5057 .optional_payload_unsafe;
5057 if (mem.eql(u8, "_", tree.tokenSlice(ident_token)))5058 const ident_bytes = tree.tokenSlice(ident_token);
5059 if (mem.eql(u8, "_", ident_bytes))
5058 break :s &then_scope.base;5060 break :s &then_scope.base;
5059 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);5061 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);
5060 const ident_name = try astgen.identAsString(ident_token);5062 const ident_name = try astgen.identAsString(ident_token);
5061 try astgen.detectLocalShadowing(&then_scope.base, ident_name, ident_token);5063 try astgen.detectLocalShadowing(&then_scope.base, ident_name, ident_token, ident_bytes);
5062 payload_val_scope = .{5064 payload_val_scope = .{
5063 .parent = &then_scope.base,5065 .parent = &then_scope.base,
5064 .gen_zir = &then_scope,5066 .gen_zir = &then_scope,
...@@ -5100,7 +5102,7 @@ fn ifExpr(...@@ -5100,7 +5102,7 @@ fn ifExpr(
5100 const error_token_str = tree.tokenSlice(error_token);5102 const error_token_str = tree.tokenSlice(error_token);
5101 if (mem.eql(u8, "_", error_token_str))5103 if (mem.eql(u8, "_", error_token_str))
5102 break :s &else_scope.base;5104 break :s &else_scope.base;
5103 try astgen.detectLocalShadowing(&else_scope.base, ident_name, error_token);5105 try astgen.detectLocalShadowing(&else_scope.base, ident_name, error_token, error_token_str);
5104 payload_val_scope = .{5106 payload_val_scope = .{
5105 .parent = &else_scope.base,5107 .parent = &else_scope.base,
5106 .gen_zir = &else_scope,5108 .gen_zir = &else_scope,
...@@ -5291,11 +5293,12 @@ fn whileExpr(...@@ -5291,11 +5293,12 @@ fn whileExpr(
5291 .err_union_payload_unsafe;5293 .err_union_payload_unsafe;
5292 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);5294 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);
5293 const ident_token = if (payload_is_ref) payload_token + 1 else payload_token;5295 const ident_token = if (payload_is_ref) payload_token + 1 else payload_token;
5294 if (mem.eql(u8, "_", tree.tokenSlice(ident_token)))5296 const ident_bytes = tree.tokenSlice(ident_token);
5297 if (mem.eql(u8, "_", ident_bytes))
5295 break :s &then_scope.base;5298 break :s &then_scope.base;
5296 const payload_name_loc = payload_token + @boolToInt(payload_is_ref);5299 const payload_name_loc = payload_token + @boolToInt(payload_is_ref);
5297 const ident_name = try astgen.identAsString(payload_name_loc);5300 const ident_name = try astgen.identAsString(payload_name_loc);
5298 try astgen.detectLocalShadowing(&then_scope.base, ident_name, payload_name_loc);5301 try astgen.detectLocalShadowing(&then_scope.base, ident_name, payload_name_loc, ident_bytes);
5299 payload_val_scope = .{5302 payload_val_scope = .{
5300 .parent = &then_scope.base,5303 .parent = &then_scope.base,
5301 .gen_zir = &then_scope,5304 .gen_zir = &then_scope,
...@@ -5316,9 +5319,10 @@ fn whileExpr(...@@ -5316,9 +5319,10 @@ fn whileExpr(
5316 .optional_payload_unsafe;5319 .optional_payload_unsafe;
5317 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);5320 const payload_inst = try then_scope.addUnNode(tag, cond.inst, node);
5318 const ident_name = try astgen.identAsString(ident_token);5321 const ident_name = try astgen.identAsString(ident_token);
5319 if (mem.eql(u8, "_", tree.tokenSlice(ident_token)))5322 const ident_bytes = tree.tokenSlice(ident_token);
5323 if (mem.eql(u8, "_", ident_bytes))
5320 break :s &then_scope.base;5324 break :s &then_scope.base;
5321 try astgen.detectLocalShadowing(&then_scope.base, ident_name, ident_token);5325 try astgen.detectLocalShadowing(&then_scope.base, ident_name, ident_token, ident_bytes);
5322 payload_val_scope = .{5326 payload_val_scope = .{
5323 .parent = &then_scope.base,5327 .parent = &then_scope.base,
5324 .gen_zir = &then_scope,5328 .gen_zir = &then_scope,
...@@ -5374,9 +5378,10 @@ fn whileExpr(...@@ -5374,9 +5378,10 @@ fn whileExpr(
5374 .err_union_code;5378 .err_union_code;
5375 const payload_inst = try else_scope.addUnNode(tag, cond.inst, node);5379 const payload_inst = try else_scope.addUnNode(tag, cond.inst, node);
5376 const ident_name = try astgen.identAsString(error_token);5380 const ident_name = try astgen.identAsString(error_token);
5377 if (mem.eql(u8, tree.tokenSlice(error_token), "_"))5381 const ident_bytes = tree.tokenSlice(error_token);
5382 if (mem.eql(u8, ident_bytes, "_"))
5378 break :s &else_scope.base;5383 break :s &else_scope.base;
5379 try astgen.detectLocalShadowing(&else_scope.base, ident_name, error_token);5384 try astgen.detectLocalShadowing(&else_scope.base, ident_name, error_token, ident_bytes);
5380 payload_val_scope = .{5385 payload_val_scope = .{
5381 .parent = &else_scope.base,5386 .parent = &else_scope.base,
5382 .gen_zir = &else_scope,5387 .gen_zir = &else_scope,
...@@ -5523,7 +5528,7 @@ fn forExpr(...@@ -5523,7 +5528,7 @@ fn forExpr(
5523 const name_str_index = try astgen.identAsString(ident);5528 const name_str_index = try astgen.identAsString(ident);
5524 const tag: Zir.Inst.Tag = if (is_ptr) .elem_ptr else .elem_val;5529 const tag: Zir.Inst.Tag = if (is_ptr) .elem_ptr else .elem_val;
5525 const payload_inst = try then_scope.addBin(tag, array_ptr, index);5530 const payload_inst = try then_scope.addBin(tag, array_ptr, index);
5526 try astgen.detectLocalShadowing(&then_scope.base, name_str_index, ident);5531 try astgen.detectLocalShadowing(&then_scope.base, name_str_index, ident, value_name);
5527 payload_val_scope = .{5532 payload_val_scope = .{
5528 .parent = &then_scope.base,5533 .parent = &then_scope.base,
5529 .gen_zir = &then_scope,5534 .gen_zir = &then_scope,
...@@ -5543,11 +5548,12 @@ fn forExpr(...@@ -5543,11 +5548,12 @@ fn forExpr(
5543 ident + 25548 ident + 2
5544 else5549 else
5545 break :blk payload_sub_scope;5550 break :blk payload_sub_scope;
5546 if (mem.eql(u8, tree.tokenSlice(index_token), "_")) {5551 const token_bytes = tree.tokenSlice(index_token);
5552 if (mem.eql(u8, token_bytes, "_")) {
5547 return astgen.failTok(index_token, "discard of index capture; omit it instead", .{});5553 return astgen.failTok(index_token, "discard of index capture; omit it instead", .{});
5548 }5554 }
5549 const index_name = try astgen.identAsString(index_token);5555 const index_name = try astgen.identAsString(index_token);
5550 try astgen.detectLocalShadowing(payload_sub_scope, index_name, index_token);5556 try astgen.detectLocalShadowing(payload_sub_scope, index_name, index_token, token_bytes);
5551 index_scope = .{5557 index_scope = .{
5552 .parent = payload_sub_scope,5558 .parent = payload_sub_scope,
5553 .gen_zir = &then_scope,5559 .gen_zir = &then_scope,
...@@ -10059,7 +10065,7 @@ fn declareNewName(...@@ -10059,7 +10065,7 @@ fn declareNewName(
10059 const ns = scope.cast(Scope.Namespace).?;10065 const ns = scope.cast(Scope.Namespace).?;
10060 const gop = try ns.decls.getOrPut(gpa, name_index);10066 const gop = try ns.decls.getOrPut(gpa, name_index);
10061 if (gop.found_existing) {10067 if (gop.found_existing) {
10062 const name = try gpa.dupe(u8, mem.spanZ(astgen.nullTerminatedString(name_index)));10068 const name = try gpa.dupe(u8, mem.span(astgen.nullTerminatedString(name_index)));
10063 defer gpa.free(name);10069 defer gpa.free(name);
10064 return astgen.failNodeNotes(node, "redeclaration of '{s}'", .{10070 return astgen.failNodeNotes(node, "redeclaration of '{s}'", .{
10065 name,10071 name,
...@@ -10094,13 +10100,17 @@ fn detectLocalShadowing(...@@ -10094,13 +10100,17 @@ fn detectLocalShadowing(
10094 scope: *Scope,10100 scope: *Scope,
10095 ident_name: u32,10101 ident_name: u32,
10096 name_token: ast.TokenIndex,10102 name_token: ast.TokenIndex,
10103 token_bytes: []const u8,
10097) !void {10104) !void {
10098 const gpa = astgen.gpa;10105 const gpa = astgen.gpa;
10099 const name_slice = mem.spanZ(astgen.nullTerminatedString(ident_name));10106 if (token_bytes[0] != '@' and isPrimitive(token_bytes)) {
10100 if (isPrimitive(name_slice)) {10107 return astgen.failTokNotes(name_token, "name shadows primitive '{s}'", .{
10101 const name = try gpa.dupe(u8, name_slice);10108 token_bytes,
10102 defer gpa.free(name);10109 }, &[_]u32{
10103 return astgen.failTok(name_token, "local shadows primitive '{s}'", .{name});10110 try astgen.errNoteTok(name_token, "consider using @\"{s}\" to disambiguate", .{
10111 token_bytes,
10112 }),
10113 });
10104 }10114 }
1010510115
10106 var s = scope;10116 var s = scope;
...@@ -10108,6 +10118,7 @@ fn detectLocalShadowing(...@@ -10108,6 +10118,7 @@ fn detectLocalShadowing(
10108 .local_val => {10118 .local_val => {
10109 const local_val = s.cast(Scope.LocalVal).?;10119 const local_val = s.cast(Scope.LocalVal).?;
10110 if (local_val.name == ident_name) {10120 if (local_val.name == ident_name) {
10121 const name_slice = mem.span(astgen.nullTerminatedString(ident_name));
10111 const name = try gpa.dupe(u8, name_slice);10122 const name = try gpa.dupe(u8, name_slice);
10112 defer gpa.free(name);10123 defer gpa.free(name);
10113 return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{10124 return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{
...@@ -10125,6 +10136,7 @@ fn detectLocalShadowing(...@@ -10125,6 +10136,7 @@ fn detectLocalShadowing(
10125 .local_ptr => {10136 .local_ptr => {
10126 const local_ptr = s.cast(Scope.LocalPtr).?;10137 const local_ptr = s.cast(Scope.LocalPtr).?;
10127 if (local_ptr.name == ident_name) {10138 if (local_ptr.name == ident_name) {
10139 const name_slice = mem.span(astgen.nullTerminatedString(ident_name));
10128 const name = try gpa.dupe(u8, name_slice);10140 const name = try gpa.dupe(u8, name_slice);
10129 defer gpa.free(name);10141 defer gpa.free(name);
10130 return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{10142 return astgen.failTokNotes(name_token, "redeclaration of {s} '{s}'", .{
...@@ -10145,6 +10157,7 @@ fn detectLocalShadowing(...@@ -10145,6 +10157,7 @@ fn detectLocalShadowing(
10145 s = ns.parent;10157 s = ns.parent;
10146 continue;10158 continue;
10147 };10159 };
10160 const name_slice = mem.span(astgen.nullTerminatedString(ident_name));
10148 const name = try gpa.dupe(u8, name_slice);10161 const name = try gpa.dupe(u8, name_slice);
10149 defer gpa.free(name);10162 defer gpa.free(name);
10150 return astgen.failTokNotes(name_token, "local shadows declaration of '{s}'", .{10163 return astgen.failTokNotes(name_token, "local shadows declaration of '{s}'", .{
test/behavior/misc.zig+4
...@@ -533,4 +533,8 @@ test "use of declaration with same name as primitive" {...@@ -533,4 +533,8 @@ test "use of declaration with same name as primitive" {
533533
534 const b: S.alias = 300;534 const b: S.alias = 300;
535 try expect(b == 300);535 try expect(b == 300);
536
537 const @"u8" = u16;
538 const c: @"u8" = 300;
539 try expect(c == 300);
536}540}
test/compile_errors.zig+2-7
...@@ -7264,14 +7264,9 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -7264,14 +7264,9 @@ pub fn addCases(ctx: *TestContext) !void {
7264 \\ const a: u8 = 300;7264 \\ const a: u8 = 300;
7265 \\ _ = a;7265 \\ _ = a;
7266 \\}7266 \\}
7267 \\export fn bar() void {
7268 \\ const @"u8" = u16;
7269 \\ const a: @"u8" = 300;
7270 \\ _ = a;
7271 \\}
7272 , &[_][]const u8{7267 , &[_][]const u8{
7273 "tmp.zig:2:11: error: local shadows primitive 'u8'",7268 "tmp.zig:2:11: error: name shadows primitive 'u8'",
7274 "tmp.zig:7:11: error: local shadows primitive 'u8'",7269 "tmp.zig:2:11: note: consider using @\"u8\" to disambiguate",
7275 });7270 });
72767271
7277 ctx.objErrStage1("primitives take precedence over declarations",7272 ctx.objErrStage1("primitives take precedence over declarations",