| ... | ... | @@ -2883,8 +2883,6 @@ fn fnDecl( |
| 2883 | 2883 | }; |
| 2884 | 2884 | const fn_name_str_index = try astgen.identAsString(fn_name_token); |
| 2885 | 2885 | |
| 2886 | | try astgen.declareNewName(scope, fn_name_str_index, decl_node, fn_name_token); |
| 2887 | | |
| 2888 | 2886 | // We insert this at the beginning so that its instruction index marks the |
| 2889 | 2887 | // start of the top level declaration. |
| 2890 | 2888 | const block_inst = try gz.addBlock(.block_inline, fn_proto.ast.proto_node); |
| ... | ... | @@ -3153,8 +3151,6 @@ fn globalVarDecl( |
| 3153 | 3151 | const name_token = var_decl.ast.mut_token + 1; |
| 3154 | 3152 | const name_str_index = try astgen.identAsString(name_token); |
| 3155 | 3153 | |
| 3156 | | try astgen.declareNewName(scope, name_str_index, node, name_token); |
| 3157 | | |
| 3158 | 3154 | var block_scope: GenZir = .{ |
| 3159 | 3155 | .parent = scope, |
| 3160 | 3156 | .decl_node_index = node, |
| ... | ... | @@ -3509,9 +3505,11 @@ fn structDeclInner( |
| 3509 | 3505 | }; |
| 3510 | 3506 | defer block_scope.instructions.deinit(gpa); |
| 3511 | 3507 | |
| 3512 | | var namespace: Scope.Namespace = .{ .parent = scope }; |
| 3508 | var namespace: Scope.Namespace = .{ .parent = scope, .node = node }; |
| 3513 | 3509 | defer namespace.decls.deinit(gpa); |
| 3514 | 3510 | |
| 3511 | try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 3512 | |
| 3515 | 3513 | var wip_decls: WipDecls = .{}; |
| 3516 | 3514 | defer wip_decls.deinit(gpa); |
| 3517 | 3515 | |
| ... | ... | @@ -3671,7 +3669,7 @@ fn structDeclInner( |
| 3671 | 3669 | const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype") |
| 3672 | 3670 | .none |
| 3673 | 3671 | 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 | 3673 | fields_data.appendAssumeCapacity(@enumToInt(field_type)); |
| 3676 | 3674 | |
| 3677 | 3675 | known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr); |
| ... | ... | @@ -3687,13 +3685,13 @@ fn structDeclInner( |
| 3687 | 3685 | (@as(u32, @boolToInt(unused)) << 31); |
| 3688 | 3686 | |
| 3689 | 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 | 3689 | fields_data.appendAssumeCapacity(@enumToInt(align_inst)); |
| 3692 | 3690 | } |
| 3693 | 3691 | if (have_value) { |
| 3694 | 3692 | const rl: ResultLoc = if (field_type == .none) .none else .{ .ty = field_type }; |
| 3695 | 3693 | |
| 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 | 3695 | fields_data.appendAssumeCapacity(@enumToInt(default_inst)); |
| 3698 | 3696 | } else if (member.comptime_token) |comptime_token| { |
| 3699 | 3697 | return astgen.failTok(comptime_token, "comptime field without default initialization value", .{}); |
| ... | ... | @@ -3756,7 +3754,7 @@ fn unionDeclInner( |
| 3756 | 3754 | node: ast.Node.Index, |
| 3757 | 3755 | members: []const ast.Node.Index, |
| 3758 | 3756 | layout: std.builtin.TypeInfo.ContainerLayout, |
| 3759 | | arg_inst: Zir.Inst.Ref, |
| 3757 | arg_node: ast.Node.Index, |
| 3760 | 3758 | have_auto_enum: bool, |
| 3761 | 3759 | ) InnerError!Zir.Inst.Ref { |
| 3762 | 3760 | const astgen = gz.astgen; |
| ... | ... | @@ -3778,9 +3776,16 @@ fn unionDeclInner( |
| 3778 | 3776 | }; |
| 3779 | 3777 | defer block_scope.instructions.deinit(gpa); |
| 3780 | 3778 | |
| 3781 | | var namespace: Scope.Namespace = .{ .parent = scope }; |
| 3779 | var namespace: Scope.Namespace = .{ .parent = scope, .node = node }; |
| 3782 | 3780 | defer namespace.decls.deinit(gpa); |
| 3783 | 3781 | |
| 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 | 3789 | var wip_decls: WipDecls = .{}; |
| 3785 | 3790 | defer wip_decls.deinit(gpa); |
| 3786 | 3791 | |
| ... | ... | @@ -3946,7 +3951,7 @@ fn unionDeclInner( |
| 3946 | 3951 | (@as(u32, @boolToInt(unused)) << 31); |
| 3947 | 3952 | |
| 3948 | 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 | 3955 | fields_data.appendAssumeCapacity(@enumToInt(field_type)); |
| 3951 | 3956 | } |
| 3952 | 3957 | if (have_align) { |
| ... | ... | @@ -4046,11 +4051,6 @@ fn containerDecl( |
| 4046 | 4051 | // We must not create any types until Sema. Here the goal is only to generate |
| 4047 | 4052 | // ZIR for all the field types, alignments, and default value expressions. |
| 4048 | 4053 | |
| 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 | 4054 | switch (token_tags[container_decl.ast.main_token]) { |
| 4055 | 4055 | .keyword_struct => { |
| 4056 | 4056 | const layout = if (container_decl.layout_token) |t| switch (token_tags[t]) { |
| ... | ... | @@ -4059,7 +4059,7 @@ fn containerDecl( |
| 4059 | 4059 | else => unreachable, |
| 4060 | 4060 | } else std.builtin.TypeInfo.ContainerLayout.Auto; |
| 4061 | 4061 | |
| 4062 | | assert(arg_inst == .none); |
| 4062 | assert(container_decl.ast.arg == 0); |
| 4063 | 4063 | |
| 4064 | 4064 | const result = try structDeclInner(gz, scope, node, container_decl, layout); |
| 4065 | 4065 | return rvalue(gz, rl, result, node); |
| ... | ... | @@ -4073,7 +4073,7 @@ fn containerDecl( |
| 4073 | 4073 | |
| 4074 | 4074 | const have_auto_enum = container_decl.ast.enum_token != null; |
| 4075 | 4075 | |
| 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 | 4077 | return rvalue(gz, rl, result, node); |
| 4078 | 4078 | }, |
| 4079 | 4079 | .keyword_enum => { |
| ... | ... | @@ -4140,7 +4140,7 @@ fn containerDecl( |
| 4140 | 4140 | } |
| 4141 | 4141 | total_fields += 1; |
| 4142 | 4142 | if (member.ast.value_expr != 0) { |
| 4143 | | if (arg_inst == .none) { |
| 4143 | if (container_decl.ast.arg == 0) { |
| 4144 | 4144 | return astgen.failNode(member.ast.value_expr, "value assigned to enum tag with inferred tag type", .{}); |
| 4145 | 4145 | } |
| 4146 | 4146 | values += 1; |
| ... | ... | @@ -4159,7 +4159,7 @@ fn containerDecl( |
| 4159 | 4159 | // must be at least one tag. |
| 4160 | 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 | 4163 | return astgen.failNodeNotes( |
| 4164 | 4164 | node, |
| 4165 | 4165 | "non-exhaustive enum missing integer tag type", |
| ... | ... | @@ -4189,9 +4189,16 @@ fn containerDecl( |
| 4189 | 4189 | }; |
| 4190 | 4190 | defer block_scope.instructions.deinit(gpa); |
| 4191 | 4191 | |
| 4192 | | var namespace: Scope.Namespace = .{ .parent = scope }; |
| 4192 | var namespace: Scope.Namespace = .{ .parent = scope, .node = node }; |
| 4193 | 4193 | defer namespace.decls.deinit(gpa); |
| 4194 | 4194 | |
| 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 | 4202 | var wip_decls: WipDecls = .{}; |
| 4196 | 4203 | defer wip_decls.deinit(gpa); |
| 4197 | 4204 | |
| ... | ... | @@ -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 | 4375 | fields_data.appendAssumeCapacity(@enumToInt(tag_value_inst)); |
| 4369 | 4376 | } |
| 4370 | 4377 | |
| ... | ... | @@ -4416,9 +4423,13 @@ fn containerDecl( |
| 4416 | 4423 | return rvalue(gz, rl, indexToRef(decl_inst), node); |
| 4417 | 4424 | }, |
| 4418 | 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 | 4429 | defer namespace.decls.deinit(gpa); |
| 4421 | 4430 | |
| 4431 | try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 4432 | |
| 4422 | 4433 | var wip_decls: WipDecls = .{}; |
| 4423 | 4434 | defer wip_decls.deinit(gpa); |
| 4424 | 4435 | |
| ... | ... | @@ -6352,73 +6363,68 @@ fn identifier( |
| 6352 | 6363 | |
| 6353 | 6364 | // Local variables, including function parameters. |
| 6354 | 6365 | const name_str_index = try astgen.identAsString(ident_token); |
| 6355 | | { |
| 6356 | | var s = scope; |
| 6357 | | var found_already: ?ast.Node.Index = null; // we have found a decl with the same name already |
| 6358 | | var hit_namespace = false; |
| 6359 | | while (true) switch (s.tag) { |
| 6360 | | .local_val => { |
| 6361 | | const local_val = s.cast(Scope.LocalVal).?; |
| 6362 | | |
| 6363 | | if (local_val.name == name_str_index) { |
| 6364 | | local_val.used = true; |
| 6365 | | // Captures of non-locals need to be emitted as decl_val or decl_ref. |
| 6366 | | // This *might* be capturable depending on if it is comptime known. |
| 6367 | | if (!hit_namespace) { |
| 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 | | } |
| 6366 | var s = scope; |
| 6367 | var found_already: ?ast.Node.Index = null; // we have found a decl with the same name already |
| 6368 | var hit_namespace: ast.Node.Index = 0; |
| 6369 | while (true) switch (s.tag) { |
| 6370 | .local_val => { |
| 6371 | const local_val = s.cast(Scope.LocalVal).?; |
| 6372 | |
| 6373 | if (local_val.name == name_str_index) { |
| 6374 | local_val.used = true; |
| 6375 | // 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. |
| 6377 | if (hit_namespace == 0) { |
| 6378 | return rvalue(gz, rl, local_val.inst, ident); |
| 6395 | 6379 | } |
| 6396 | | s = local_ptr.parent; |
| 6397 | | }, |
| 6398 | | .gen_zir => s = s.cast(GenZir).?.parent, |
| 6399 | | .defer_normal, .defer_error => s = s.cast(Scope.Defer).?.parent, |
| 6400 | | // look for ambiguous references to decls |
| 6401 | | .namespace => { |
| 6402 | | const ns = s.cast(Scope.Namespace).?; |
| 6403 | | if (ns.decls.get(name_str_index)) |i| { |
| 6404 | | if (found_already) |f| |
| 6405 | | return astgen.failNodeNotes(ident, "ambiguous reference", .{}, &.{ |
| 6406 | | try astgen.errNoteNode(i, "declared here", .{}), |
| 6407 | | try astgen.errNoteNode(f, "also declared here", .{}), |
| 6408 | | }) |
| 6380 | } |
| 6381 | s = local_val.parent; |
| 6382 | }, |
| 6383 | .local_ptr => { |
| 6384 | const local_ptr = s.cast(Scope.LocalPtr).?; |
| 6385 | if (local_ptr.name == name_str_index) { |
| 6386 | local_ptr.used = true; |
| 6387 | if (hit_namespace != 0) { |
| 6388 | if (local_ptr.maybe_comptime) |
| 6389 | break |
| 6409 | 6390 | 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; |
| 6413 | | s = ns.parent; |
| 6414 | | }, |
| 6415 | | .top => break, |
| 6416 | | }; |
| 6417 | | } |
| 6396 | switch (rl) { |
| 6397 | .ref, .none_or_ref => return local_ptr.ptr, |
| 6398 | else => { |
| 6399 | const loaded = try gz.addUnNode(.load, local_ptr.ptr, ident); |
| 6400 | return rvalue(gz, rl, loaded, ident); |
| 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 | }; |
| 6418 | 6425 | |
| 6419 | | // We can't look up Decls until Sema because the same ZIR code is supposed to be |
| 6420 | | // used for multiple generic instantiations, and this may refer to a different Decl |
| 6421 | | // depending on the scope, determined by the generic instantiation. |
| 6426 | // Decl references happen by name rather than ZIR index so that when unrelated |
| 6427 | // decls are modified, ZIR code containing references to them can be unmodified. |
| 6422 | 6428 | switch (rl) { |
| 6423 | 6429 | .ref, .none_or_ref => return gz.addStrTok(.decl_ref, name_str_index, ident_token), |
| 6424 | 6430 | else => { |
| ... | ... | @@ -8941,6 +8947,7 @@ const Scope = struct { |
| 8941 | 8947 | /// Maps string table index to the source location of declaration, |
| 8942 | 8948 | /// for the purposes of reporting name shadowing compile errors. |
| 8943 | 8949 | decls: std.AutoHashMapUnmanaged(u32, ast.Node.Index) = .{}, |
| 8950 | node: ast.Node.Index, |
| 8944 | 8951 | }; |
| 8945 | 8952 | |
| 8946 | 8953 | const Top = struct { |
| ... | ... | @@ -10014,53 +10021,6 @@ fn nullTerminatedString(astgen: AstGen, index: usize) [*:0]const u8 { |
| 10014 | 10021 | return @ptrCast([*:0]const u8, astgen.string_bytes.items.ptr) + index; |
| 10015 | 10022 | } |
| 10016 | 10023 | |
| 10017 | | fn 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 | | |
| 10064 | 10024 | fn isPrimitive(name: []const u8) bool { |
| 10065 | 10025 | if (simple_types.get(name) != null) return true; |
| 10066 | 10026 | if (name.len < 2) return false; |
| ... | ... | @@ -10183,3 +10143,56 @@ fn refToIndex(inst: Zir.Inst.Ref) ?Zir.Inst.Index { |
| 10183 | 10143 | return null; |
| 10184 | 10144 | } |
| 10185 | 10145 | } |
| 10146 | |
| 10147 | fn 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 | } |