authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-28 15:15:46-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-28 16:04:38-07:00
log4bb5d17edc85eac74626224810d6a44a3c73cca3
tree1464b91474019c5c047ba66bae7197fa7e6d73bf
parent05cf44933d753f7a5a53ab289ea60fd43761de57

AstGen: pre-scan all decls in a namespace

Also: * improve the "ambiguous reference" error by swapping the order of "declared here" and "also declared here" notes. * improve the "not accessible from inner function" error: - point out that it has to do with the thing being mutable - eliminate the incorrect association with it being a function - note where it crosses a namespace boundary * struct field types are evaluated in a context that has the struct namespace visible. Likewise with align expressions, linksection expressions, enum tag values, and union/enum tag argument expressions. Closes #9194 Closes #9622

6 files changed, 183 insertions(+), 141 deletions(-)

src/AstGen.zig+146-133
...@@ -2883,8 +2883,6 @@ fn fnDecl(...@@ -2883,8 +2883,6 @@ fn fnDecl(
2883 };2883 };
2884 const fn_name_str_index = try astgen.identAsString(fn_name_token);2884 const fn_name_str_index = try astgen.identAsString(fn_name_token);
28852885
2886 try astgen.declareNewName(scope, fn_name_str_index, decl_node, fn_name_token);
2887
2888 // We insert this at the beginning so that its instruction index marks the2886 // We insert this at the beginning so that its instruction index marks the
2889 // start of the top level declaration.2887 // start of the top level declaration.
2890 const block_inst = try gz.addBlock(.block_inline, fn_proto.ast.proto_node);2888 const block_inst = try gz.addBlock(.block_inline, fn_proto.ast.proto_node);
...@@ -3153,8 +3151,6 @@ fn globalVarDecl(...@@ -3153,8 +3151,6 @@ fn globalVarDecl(
3153 const name_token = var_decl.ast.mut_token + 1;3151 const name_token = var_decl.ast.mut_token + 1;
3154 const name_str_index = try astgen.identAsString(name_token);3152 const name_str_index = try astgen.identAsString(name_token);
31553153
3156 try astgen.declareNewName(scope, name_str_index, node, name_token);
3157
3158 var block_scope: GenZir = .{3154 var block_scope: GenZir = .{
3159 .parent = scope,3155 .parent = scope,
3160 .decl_node_index = node,3156 .decl_node_index = node,
...@@ -3509,9 +3505,11 @@ fn structDeclInner(...@@ -3509,9 +3505,11 @@ fn structDeclInner(
3509 };3505 };
3510 defer block_scope.instructions.deinit(gpa);3506 defer block_scope.instructions.deinit(gpa);
35113507
3512 var namespace: Scope.Namespace = .{ .parent = scope };3508 var namespace: Scope.Namespace = .{ .parent = scope, .node = node };
3513 defer namespace.decls.deinit(gpa);3509 defer namespace.decls.deinit(gpa);
35143510
3511 try astgen.scanDecls(&namespace, container_decl.ast.members);
3512
3515 var wip_decls: WipDecls = .{};3513 var wip_decls: WipDecls = .{};
3516 defer wip_decls.deinit(gpa);3514 defer wip_decls.deinit(gpa);
35173515
...@@ -3671,7 +3669,7 @@ fn structDeclInner(...@@ -3671,7 +3669,7 @@ fn structDeclInner(
3671 const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype")3669 const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype")
3672 .none3670 .none
3673 else3671 else
3674 try typeExpr(&block_scope, &block_scope.base, member.ast.type_expr);3672 try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
3675 fields_data.appendAssumeCapacity(@enumToInt(field_type));3673 fields_data.appendAssumeCapacity(@enumToInt(field_type));
36763674
3677 known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr);3675 known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr);
...@@ -3687,13 +3685,13 @@ fn structDeclInner(...@@ -3687,13 +3685,13 @@ fn structDeclInner(
3687 (@as(u32, @boolToInt(unused)) << 31);3685 (@as(u32, @boolToInt(unused)) << 31);
36883686
3689 if (have_align) {3687 if (have_align) {
3690 const align_inst = try expr(&block_scope, &block_scope.base, align_rl, member.ast.align_expr);3688 const align_inst = try expr(&block_scope, &namespace.base, align_rl, member.ast.align_expr);
3691 fields_data.appendAssumeCapacity(@enumToInt(align_inst));3689 fields_data.appendAssumeCapacity(@enumToInt(align_inst));
3692 }3690 }
3693 if (have_value) {3691 if (have_value) {
3694 const rl: ResultLoc = if (field_type == .none) .none else .{ .ty = field_type };3692 const rl: ResultLoc = if (field_type == .none) .none else .{ .ty = field_type };
36953693
3696 const default_inst = try expr(&block_scope, &block_scope.base, rl, member.ast.value_expr);3694 const default_inst = try expr(&block_scope, &namespace.base, rl, member.ast.value_expr);
3697 fields_data.appendAssumeCapacity(@enumToInt(default_inst));3695 fields_data.appendAssumeCapacity(@enumToInt(default_inst));
3698 } else if (member.comptime_token) |comptime_token| {3696 } else if (member.comptime_token) |comptime_token| {
3699 return astgen.failTok(comptime_token, "comptime field without default initialization value", .{});3697 return astgen.failTok(comptime_token, "comptime field without default initialization value", .{});
...@@ -3756,7 +3754,7 @@ fn unionDeclInner(...@@ -3756,7 +3754,7 @@ fn unionDeclInner(
3756 node: ast.Node.Index,3754 node: ast.Node.Index,
3757 members: []const ast.Node.Index,3755 members: []const ast.Node.Index,
3758 layout: std.builtin.TypeInfo.ContainerLayout,3756 layout: std.builtin.TypeInfo.ContainerLayout,
3759 arg_inst: Zir.Inst.Ref,3757 arg_node: ast.Node.Index,
3760 have_auto_enum: bool,3758 have_auto_enum: bool,
3761) InnerError!Zir.Inst.Ref {3759) InnerError!Zir.Inst.Ref {
3762 const astgen = gz.astgen;3760 const astgen = gz.astgen;
...@@ -3778,9 +3776,16 @@ fn unionDeclInner(...@@ -3778,9 +3776,16 @@ fn unionDeclInner(
3778 };3776 };
3779 defer block_scope.instructions.deinit(gpa);3777 defer block_scope.instructions.deinit(gpa);
37803778
3781 var namespace: Scope.Namespace = .{ .parent = scope };3779 var namespace: Scope.Namespace = .{ .parent = scope, .node = node };
3782 defer namespace.decls.deinit(gpa);3780 defer namespace.decls.deinit(gpa);
37833781
3782 try astgen.scanDecls(&namespace, members);
3783
3784 const arg_inst: Zir.Inst.Ref = if (arg_node != 0)
3785 try typeExpr(gz, &namespace.base, arg_node)
3786 else
3787 .none;
3788
3784 var wip_decls: WipDecls = .{};3789 var wip_decls: WipDecls = .{};
3785 defer wip_decls.deinit(gpa);3790 defer wip_decls.deinit(gpa);
37863791
...@@ -3946,7 +3951,7 @@ fn unionDeclInner(...@@ -3946,7 +3951,7 @@ fn unionDeclInner(
3946 (@as(u32, @boolToInt(unused)) << 31);3951 (@as(u32, @boolToInt(unused)) << 31);
39473952
3948 if (have_type and node_tags[member.ast.type_expr] != .@"anytype") {3953 if (have_type and node_tags[member.ast.type_expr] != .@"anytype") {
3949 const field_type = try typeExpr(&block_scope, &block_scope.base, member.ast.type_expr);3954 const field_type = try typeExpr(&block_scope, &namespace.base, member.ast.type_expr);
3950 fields_data.appendAssumeCapacity(@enumToInt(field_type));3955 fields_data.appendAssumeCapacity(@enumToInt(field_type));
3951 }3956 }
3952 if (have_align) {3957 if (have_align) {
...@@ -4046,11 +4051,6 @@ fn containerDecl(...@@ -4046,11 +4051,6 @@ fn containerDecl(
4046 // We must not create any types until Sema. Here the goal is only to generate4051 // We must not create any types until Sema. Here the goal is only to generate
4047 // ZIR for all the field types, alignments, and default value expressions.4052 // ZIR for all the field types, alignments, and default value expressions.
40484053
4049 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)
4050 try comptimeExpr(gz, scope, .{ .ty = .type_type }, container_decl.ast.arg)
4051 else
4052 .none;
4053
4054 switch (token_tags[container_decl.ast.main_token]) {4054 switch (token_tags[container_decl.ast.main_token]) {
4055 .keyword_struct => {4055 .keyword_struct => {
4056 const layout = if (container_decl.layout_token) |t| switch (token_tags[t]) {4056 const layout = if (container_decl.layout_token) |t| switch (token_tags[t]) {
...@@ -4059,7 +4059,7 @@ fn containerDecl(...@@ -4059,7 +4059,7 @@ fn containerDecl(
4059 else => unreachable,4059 else => unreachable,
4060 } else std.builtin.TypeInfo.ContainerLayout.Auto;4060 } else std.builtin.TypeInfo.ContainerLayout.Auto;
40614061
4062 assert(arg_inst == .none);4062 assert(container_decl.ast.arg == 0);
40634063
4064 const result = try structDeclInner(gz, scope, node, container_decl, layout);4064 const result = try structDeclInner(gz, scope, node, container_decl, layout);
4065 return rvalue(gz, rl, result, node);4065 return rvalue(gz, rl, result, node);
...@@ -4073,7 +4073,7 @@ fn containerDecl(...@@ -4073,7 +4073,7 @@ fn containerDecl(
40734073
4074 const have_auto_enum = container_decl.ast.enum_token != null;4074 const have_auto_enum = container_decl.ast.enum_token != null;
40754075
4076 const result = try unionDeclInner(gz, scope, node, container_decl.ast.members, layout, arg_inst, have_auto_enum);4076 const result = try unionDeclInner(gz, scope, node, container_decl.ast.members, layout, container_decl.ast.arg, have_auto_enum);
4077 return rvalue(gz, rl, result, node);4077 return rvalue(gz, rl, result, node);
4078 },4078 },
4079 .keyword_enum => {4079 .keyword_enum => {
...@@ -4140,7 +4140,7 @@ fn containerDecl(...@@ -4140,7 +4140,7 @@ fn containerDecl(
4140 }4140 }
4141 total_fields += 1;4141 total_fields += 1;
4142 if (member.ast.value_expr != 0) {4142 if (member.ast.value_expr != 0) {
4143 if (arg_inst == .none) {4143 if (container_decl.ast.arg == 0) {
4144 return astgen.failNode(member.ast.value_expr, "value assigned to enum tag with inferred tag type", .{});4144 return astgen.failNode(member.ast.value_expr, "value assigned to enum tag with inferred tag type", .{});
4145 }4145 }
4146 values += 1;4146 values += 1;
...@@ -4159,7 +4159,7 @@ fn containerDecl(...@@ -4159,7 +4159,7 @@ fn containerDecl(
4159 // must be at least one tag.4159 // must be at least one tag.
4160 return astgen.failNode(node, "enum declarations must have at least one tag", .{});4160 return astgen.failNode(node, "enum declarations must have at least one tag", .{});
4161 }4161 }
4162 if (counts.nonexhaustive_node != 0 and arg_inst == .none) {4162 if (counts.nonexhaustive_node != 0 and container_decl.ast.arg == 0) {
4163 return astgen.failNodeNotes(4163 return astgen.failNodeNotes(
4164 node,4164 node,
4165 "non-exhaustive enum missing integer tag type",4165 "non-exhaustive enum missing integer tag type",
...@@ -4189,9 +4189,16 @@ fn containerDecl(...@@ -4189,9 +4189,16 @@ fn containerDecl(
4189 };4189 };
4190 defer block_scope.instructions.deinit(gpa);4190 defer block_scope.instructions.deinit(gpa);
41914191
4192 var namespace: Scope.Namespace = .{ .parent = scope };4192 var namespace: Scope.Namespace = .{ .parent = scope, .node = node };
4193 defer namespace.decls.deinit(gpa);4193 defer namespace.decls.deinit(gpa);
41944194
4195 try astgen.scanDecls(&namespace, container_decl.ast.members);
4196
4197 const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0)
4198 try comptimeExpr(gz, &namespace.base, .{ .ty = .type_type }, container_decl.ast.arg)
4199 else
4200 .none;
4201
4195 var wip_decls: WipDecls = .{};4202 var wip_decls: WipDecls = .{};
4196 defer wip_decls.deinit(gpa);4203 defer wip_decls.deinit(gpa);
41974204
...@@ -4364,7 +4371,7 @@ fn containerDecl(...@@ -4364,7 +4371,7 @@ fn containerDecl(
4364 },4371 },
4365 );4372 );
4366 }4373 }
4367 const tag_value_inst = try expr(&block_scope, &block_scope.base, .{ .ty = arg_inst }, member.ast.value_expr);4374 const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .ty = arg_inst }, member.ast.value_expr);
4368 fields_data.appendAssumeCapacity(@enumToInt(tag_value_inst));4375 fields_data.appendAssumeCapacity(@enumToInt(tag_value_inst));
4369 }4376 }
43704377
...@@ -4416,9 +4423,13 @@ fn containerDecl(...@@ -4416,9 +4423,13 @@ fn containerDecl(
4416 return rvalue(gz, rl, indexToRef(decl_inst), node);4423 return rvalue(gz, rl, indexToRef(decl_inst), node);
4417 },4424 },
4418 .keyword_opaque => {4425 .keyword_opaque => {
4419 var namespace: Scope.Namespace = .{ .parent = scope };4426 assert(container_decl.ast.arg == 0);
4427
4428 var namespace: Scope.Namespace = .{ .parent = scope, .node = node };
4420 defer namespace.decls.deinit(gpa);4429 defer namespace.decls.deinit(gpa);
44214430
4431 try astgen.scanDecls(&namespace, container_decl.ast.members);
4432
4422 var wip_decls: WipDecls = .{};4433 var wip_decls: WipDecls = .{};
4423 defer wip_decls.deinit(gpa);4434 defer wip_decls.deinit(gpa);
44244435
...@@ -6352,73 +6363,68 @@ fn identifier(...@@ -6352,73 +6363,68 @@ fn identifier(
63526363
6353 // Local variables, including function parameters.6364 // Local variables, including function parameters.
6354 const name_str_index = try astgen.identAsString(ident_token);6365 const name_str_index = try astgen.identAsString(ident_token);
6355 {6366 var s = scope;
6356 var s = scope;6367 var found_already: ?ast.Node.Index = null; // we have found a decl with the same name already
6357 var found_already: ?ast.Node.Index = null; // we have found a decl with the same name already6368 var hit_namespace: ast.Node.Index = 0;
6358 var hit_namespace = false;6369 while (true) switch (s.tag) {
6359 while (true) switch (s.tag) {6370 .local_val => {
6360 .local_val => {6371 const local_val = s.cast(Scope.LocalVal).?;
6361 const local_val = s.cast(Scope.LocalVal).?;6372
63626373 if (local_val.name == name_str_index) {
6363 if (local_val.name == name_str_index) {6374 local_val.used = true;
6364 local_val.used = true;6375 // Captures of non-locals need to be emitted as decl_val or decl_ref.
6365 // Captures of non-locals need to be emitted as decl_val or decl_ref.6376 // This *might* be capturable depending on if it is comptime known.
6366 // This *might* be capturable depending on if it is comptime known.6377 if (hit_namespace == 0) {
6367 if (!hit_namespace) {6378 return rvalue(gz, rl, local_val.inst, ident);
6368 return rvalue(gz, rl, local_val.inst, ident);
6369 }
6370 }
6371 s = local_val.parent;
6372 },
6373 .local_ptr => {
6374 const local_ptr = s.cast(Scope.LocalPtr).?;
6375 if (local_ptr.name == name_str_index) {
6376 local_ptr.used = true;
6377 if (hit_namespace) {
6378 if (local_ptr.maybe_comptime)
6379 break
6380 else
6381 return astgen.failNodeNotes(ident, "'{s}' not accessible from inner function", .{ident_name}, &.{
6382 try astgen.errNoteTok(local_ptr.token_src, "declared here", .{}),
6383 // TODO add crossed function definition here note.
6384 // Maybe add a note to the error about it being because of the var,
6385 // maybe recommend copying it into a const variable. -SpexGuy
6386 });
6387 }
6388 switch (rl) {
6389 .ref, .none_or_ref => return local_ptr.ptr,
6390 else => {
6391 const loaded = try gz.addUnNode(.load, local_ptr.ptr, ident);
6392 return rvalue(gz, rl, loaded, ident);
6393 },
6394 }
6395 }6379 }
6396 s = local_ptr.parent;6380 }
6397 },6381 s = local_val.parent;
6398 .gen_zir => s = s.cast(GenZir).?.parent,6382 },
6399 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,6383 .local_ptr => {
6400 // look for ambiguous references to decls6384 const local_ptr = s.cast(Scope.LocalPtr).?;
6401 .namespace => {6385 if (local_ptr.name == name_str_index) {
6402 const ns = s.cast(Scope.Namespace).?;6386 local_ptr.used = true;
6403 if (ns.decls.get(name_str_index)) |i| {6387 if (hit_namespace != 0) {
6404 if (found_already) |f|6388 if (local_ptr.maybe_comptime)
6405 return astgen.failNodeNotes(ident, "ambiguous reference", .{}, &.{6389 break
6406 try astgen.errNoteNode(i, "declared here", .{}),
6407 try astgen.errNoteNode(f, "also declared here", .{}),
6408 })
6409 else6390 else
6410 found_already = i;6391 return astgen.failNodeNotes(ident, "mutable '{s}' not accessible from here", .{ident_name}, &.{
6392 try astgen.errNoteTok(local_ptr.token_src, "declared mutable here", .{}),
6393 try astgen.errNoteNode(hit_namespace, "crosses namespace boundary here", .{}),
6394 });
6411 }6395 }
6412 hit_namespace = true;6396 switch (rl) {
6413 s = ns.parent;6397 .ref, .none_or_ref => return local_ptr.ptr,
6414 },6398 else => {
6415 .top => break,6399 const loaded = try gz.addUnNode(.load, local_ptr.ptr, ident);
6416 };6400 return rvalue(gz, rl, loaded, ident);
6417 }6401 },
6402 }
6403 }
6404 s = local_ptr.parent;
6405 },
6406 .gen_zir => s = s.cast(GenZir).?.parent,
6407 .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent,
6408 .namespace => {
6409 const ns = s.cast(Scope.Namespace).?;
6410 if (ns.decls.get(name_str_index)) |i| {
6411 if (found_already) |f| {
6412 return astgen.failNodeNotes(ident, "ambiguous reference", .{}, &.{
6413 try astgen.errNoteNode(f, "declared here", .{}),
6414 try astgen.errNoteNode(i, "also declared here", .{}),
6415 });
6416 }
6417 // We found a match but must continue looking for ambiguous references to decls.
6418 found_already = i;
6419 }
6420 hit_namespace = ns.node;
6421 s = ns.parent;
6422 },
6423 .top => break,
6424 };
64186425
6419 // We can't look up Decls until Sema because the same ZIR code is supposed to be6426 // Decl references happen by name rather than ZIR index so that when unrelated
6420 // used for multiple generic instantiations, and this may refer to a different Decl6427 // decls are modified, ZIR code containing references to them can be unmodified.
6421 // depending on the scope, determined by the generic instantiation.
6422 switch (rl) {6428 switch (rl) {
6423 .ref, .none_or_ref => return gz.addStrTok(.decl_ref, name_str_index, ident_token),6429 .ref, .none_or_ref => return gz.addStrTok(.decl_ref, name_str_index, ident_token),
6424 else => {6430 else => {
...@@ -8941,6 +8947,7 @@ const Scope = struct {...@@ -8941,6 +8947,7 @@ const Scope = struct {
8941 /// Maps string table index to the source location of declaration,8947 /// Maps string table index to the source location of declaration,
8942 /// for the purposes of reporting name shadowing compile errors.8948 /// for the purposes of reporting name shadowing compile errors.
8943 decls: std.AutoHashMapUnmanaged(u32, ast.Node.Index) = .{},8949 decls: std.AutoHashMapUnmanaged(u32, ast.Node.Index) = .{},
8950 node: ast.Node.Index,
8944 };8951 };
89458952
8946 const Top = struct {8953 const Top = struct {
...@@ -10014,53 +10021,6 @@ fn nullTerminatedString(astgen: AstGen, index: usize) [*:0]const u8 {...@@ -10014,53 +10021,6 @@ fn nullTerminatedString(astgen: AstGen, index: usize) [*:0]const u8 {
10014 return @ptrCast([*:0]const u8, astgen.string_bytes.items.ptr) + index;10021 return @ptrCast([*:0]const u8, astgen.string_bytes.items.ptr) + index;
10015}10022}
1001610023
10017fn declareNewName(
10018 astgen: *AstGen,
10019 start_scope: *Scope,
10020 name_index: u32,
10021 node: ast.Node.Index,
10022 name_token: ast.TokenIndex,
10023) !void {
10024 const gpa = astgen.gpa;
10025
10026 const token_bytes = astgen.tree.tokenSlice(name_token);
10027 if (token_bytes[0] != '@' and isPrimitive(token_bytes)) {
10028 return astgen.failTokNotes(name_token, "name shadows primitive '{s}'", .{
10029 token_bytes,
10030 }, &[_]u32{
10031 try astgen.errNoteTok(name_token, "consider using @\"{s}\" to disambiguate", .{
10032 token_bytes,
10033 }),
10034 });
10035 }
10036
10037 var scope = start_scope;
10038 while (true) {
10039 switch (scope.tag) {
10040 .gen_zir => scope = scope.cast(GenZir).?.parent,
10041 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
10042 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
10043 .defer_normal, .defer_error => scope = scope.cast(Scope.Defer).?.parent,
10044 .namespace => {
10045 const ns = scope.cast(Scope.Namespace).?;
10046 const gop = try ns.decls.getOrPut(gpa, name_index);
10047 if (gop.found_existing) {
10048 const name = try gpa.dupe(u8, mem.span(astgen.nullTerminatedString(name_index)));
10049 defer gpa.free(name);
10050 return astgen.failNodeNotes(node, "redeclaration of '{s}'", .{
10051 name,
10052 }, &[_]u32{
10053 try astgen.errNoteNode(gop.value_ptr.*, "other declaration here", .{}),
10054 });
10055 }
10056 gop.value_ptr.* = node;
10057 break;
10058 },
10059 .top => break,
10060 }
10061 }
10062}
10063
10064fn isPrimitive(name: []const u8) bool {10024fn isPrimitive(name: []const u8) bool {
10065 if (simple_types.get(name) != null) return true;10025 if (simple_types.get(name) != null) return true;
10066 if (name.len < 2) return false;10026 if (name.len < 2) return false;
...@@ -10183,3 +10143,56 @@ fn refToIndex(inst: Zir.Inst.Ref) ?Zir.Inst.Index {...@@ -10183,3 +10143,56 @@ fn refToIndex(inst: Zir.Inst.Ref) ?Zir.Inst.Index {
10183 return null;10143 return null;
10184 }10144 }
10185}10145}
10146
10147fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const ast.Node.Index) !void {
10148 const gpa = astgen.gpa;
10149 const tree = astgen.tree;
10150 const node_tags = tree.nodes.items(.tag);
10151 const main_tokens = tree.nodes.items(.main_token);
10152 for (members) |member_node| {
10153 const name_token = switch (node_tags[member_node]) {
10154 .fn_decl,
10155 .fn_proto_simple,
10156 .fn_proto_multi,
10157 .fn_proto_one,
10158 .fn_proto,
10159 .global_var_decl,
10160 .local_var_decl,
10161 .simple_var_decl,
10162 .aligned_var_decl,
10163 => main_tokens[member_node] + 1,
10164
10165 else => continue,
10166 };
10167
10168 const token_bytes = astgen.tree.tokenSlice(name_token);
10169 if (token_bytes[0] != '@' and isPrimitive(token_bytes)) {
10170 switch (astgen.failTokNotes(name_token, "name shadows primitive '{s}'", .{
10171 token_bytes,
10172 }, &[_]u32{
10173 try astgen.errNoteTok(name_token, "consider using @\"{s}\" to disambiguate", .{
10174 token_bytes,
10175 }),
10176 })) {
10177 error.AnalysisFail => continue,
10178 error.OutOfMemory => return error.OutOfMemory,
10179 }
10180 }
10181
10182 const name_str_index = try astgen.identAsString(name_token);
10183 const gop = try namespace.decls.getOrPut(gpa, name_str_index);
10184 if (gop.found_existing) {
10185 const name = try gpa.dupe(u8, mem.span(astgen.nullTerminatedString(name_str_index)));
10186 defer gpa.free(name);
10187 switch (astgen.failNodeNotes(member_node, "redeclaration of '{s}'", .{
10188 name,
10189 }, &[_]u32{
10190 try astgen.errNoteNode(gop.value_ptr.*, "other declaration here", .{}),
10191 })) {
10192 error.AnalysisFail => continue,
10193 error.OutOfMemory => return error.OutOfMemory,
10194 }
10195 }
10196 gop.value_ptr.* = member_node;
10197 }
10198}
src/Module.zig+4-1
...@@ -2648,7 +2648,10 @@ pub fn astGenFile(mod: *Module, file: *Scope.File) !void {...@@ -2648,7 +2648,10 @@ pub fn astGenFile(mod: *Module, file: *Scope.File) !void {
2648 undefined;2648 undefined;
2649 defer if (data_has_safety_tag) gpa.free(safety_buffer);2649 defer if (data_has_safety_tag) gpa.free(safety_buffer);
2650 const data_ptr = if (data_has_safety_tag)2650 const data_ptr = if (data_has_safety_tag)
2651 @ptrCast([*]const u8, safety_buffer.ptr)2651 if (file.zir.instructions.len == 0)
2652 @as([*]const u8, undefined)
2653 else
2654 @ptrCast([*]const u8, safety_buffer.ptr)
2652 else2655 else
2653 @ptrCast([*]const u8, file.zir.instructions.items(.data).ptr);2656 @ptrCast([*]const u8, file.zir.instructions.items(.data).ptr);
2654 if (data_has_safety_tag) {2657 if (data_has_safety_tag) {
test/behavior/generics.zig+2-1
...@@ -91,7 +91,8 @@ test "type constructed by comptime function call" {...@@ -91,7 +91,8 @@ test "type constructed by comptime function call" {
91}91}
9292
93fn SimpleList(comptime L: usize) type {93fn SimpleList(comptime L: usize) type {
94 var T = u8;94 var mutable_T = u8;
95 const T = mutable_T;
95 return struct {96 return struct {
96 array: [L]T,97 array: [L]T,
97 };98 };
test/behavior/misc.zig+2-2
...@@ -506,7 +506,7 @@ test "lazy typeInfo value as generic parameter" {...@@ -506,7 +506,7 @@ test "lazy typeInfo value as generic parameter" {
506 S.foo(@typeInfo(@TypeOf(.{})));506 S.foo(@typeInfo(@TypeOf(.{})));
507}507}
508508
509fn A() type {509fn ZA() type {
510 return struct {510 return struct {
511 b: B(),511 b: B(),
512512
...@@ -520,7 +520,7 @@ fn A() type {...@@ -520,7 +520,7 @@ fn A() type {
520 };520 };
521}521}
522test "non-ambiguous reference of shadowed decls" {522test "non-ambiguous reference of shadowed decls" {
523 try expect(A().B().Self != A().Self);523 try expect(ZA().B().Self != ZA().Self);
524}524}
525525
526test "use of declaration with same name as primitive" {526test "use of declaration with same name as primitive" {
test/cases.zig+5-4
...@@ -984,8 +984,8 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -984,8 +984,8 @@ pub fn addCases(ctx: *TestContext) !void {
984 \\};984 \\};
985 , &.{985 , &.{
986 ":4:17: error: ambiguous reference",986 ":4:17: error: ambiguous reference",
987 ":1:1: note: declared here",987 ":2:5: note: declared here",
988 ":2:5: note: also declared here",988 ":1:1: note: also declared here",
989 });989 });
990990
991 ctx.compileError("inner func accessing outer var", linux_x64,991 ctx.compileError("inner func accessing outer var", linux_x64,
...@@ -999,8 +999,9 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -999,8 +999,9 @@ pub fn addCases(ctx: *TestContext) !void {
999 \\ _ = S;999 \\ _ = S;
1000 \\}1000 \\}
1001 , &.{1001 , &.{
1002 ":5:20: error: 'bar' not accessible from inner function",1002 ":5:20: error: mutable 'bar' not accessible from here",
1003 ":2:9: note: declared here",1003 ":2:9: note: declared mutable here",
1004 ":3:15: note: crosses namespace boundary here",
1004 });1005 });
10051006
1006 ctx.compileError("global variable redeclaration", linux_x64,1007 ctx.compileError("global variable redeclaration", linux_x64,
test/compile_errors.zig+24
...@@ -5342,6 +5342,17 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -5342,6 +5342,17 @@ pub fn addCases(ctx: *TestContext) !void {
5342 "tmp.zig:2:1: note: declared here",5342 "tmp.zig:2:1: note: declared here",
5343 });5343 });
53445344
5345 ctx.objErrStage1("local shadows global that occurs later",
5346 \\pub fn main() void {
5347 \\ var foo = true;
5348 \\ _ = foo;
5349 \\}
5350 \\fn foo() void {}
5351 , &[_][]const u8{
5352 "tmp.zig:2:9: error: local shadows declaration of 'foo'",
5353 "tmp.zig:5:1: note: declared here",
5354 });
5355
5345 ctx.objErrStage1("switch expression - missing enumeration prong",5356 ctx.objErrStage1("switch expression - missing enumeration prong",
5346 \\const Number = enum {5357 \\const Number = enum {
5347 \\ One,5358 \\ One,
...@@ -8814,4 +8825,17 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -8814,4 +8825,17 @@ pub fn addCases(ctx: *TestContext) !void {
8814 , &[_][]const u8{8825 , &[_][]const u8{
8815 "error: Unsupported OS",8826 "error: Unsupported OS",
8816 });8827 });
8828
8829 ctx.objErrStage1("attempt to close over comptime variable from outer scope",
8830 \\fn SimpleList(comptime L: usize) type {
8831 \\ var T = u8;
8832 \\ return struct {
8833 \\ array: [L]T,
8834 \\ };
8835 \\}
8836 , &[_][]const u8{
8837 "tmp.zig:4:19: error: mutable 'T' not accessible from here",
8838 "tmp.zig:2:9: note: declared mutable here",
8839 "tmp.zig:3:12: note: crosses namespace boundary here",
8840 });
8817}8841}