diff --git a/toolchain/check/eval.cpp b/toolchain/check/eval.cpp index 3dec0d4fceed..06a133fc071d 100644 --- a/toolchain/check/eval.cpp +++ b/toolchain/check/eval.cpp @@ -1893,16 +1893,16 @@ auto TryEvalBlockForSpecific(Context& context, SemIRLoc loc, Diagnostics::AnnotationScope annotate_diagnostics( &context.emitter(), [&](auto& builder) { CARBON_DIAGNOSTIC(ResolvingSpecificHere, Note, "in {0} used here", - InstIdAsType); - builder.Note(loc, ResolvingSpecificHere, - GetInstForSpecific(context, specific_id)); + SemIR::SpecificId); + builder.Note(loc, ResolvingSpecificHere, specific_id); }); for (auto [i, inst_id] : llvm::enumerate(eval_block)) { auto const_id = TryEvalInstInContext(eval_context, inst_id, context.insts().Get(inst_id)); result[i] = context.constant_values().GetInstId(const_id); - CARBON_CHECK(result[i].has_value()); + CARBON_CHECK(result[i].has_value(), "Failed to evaluate {0} in eval block", + context.insts().Get(inst_id)); } return context.inst_blocks().Add(result); diff --git a/toolchain/check/generic.cpp b/toolchain/check/generic.cpp index 43ff2e366895..0da9d57b4436 100644 --- a/toolchain/check/generic.cpp +++ b/toolchain/check/generic.cpp @@ -608,40 +608,6 @@ auto ResolveSpecificDefinition(Context& context, SemIRLoc loc, return true; } -auto GetInstForSpecific(Context& context, SemIR::SpecificId specific_id) - -> SemIR::InstId { - CARBON_CHECK(specific_id.has_value()); - const auto& specific = context.specifics().Get(specific_id); - const auto& generic = context.generics().Get(specific.generic_id); - auto decl = context.insts().Get(generic.decl_id); - CARBON_KIND_SWITCH(decl) { - case CARBON_KIND(SemIR::ClassDecl class_decl): { - return context.types().GetInstId( - GetClassType(context, class_decl.class_id, specific_id)); - } - case CARBON_KIND(SemIR::InterfaceDecl interface_decl): { - return context.types().GetInstId( - GetInterfaceType(context, interface_decl.interface_id, specific_id)); - } - case SemIR::FunctionDecl::Kind: { - return context.constant_values().GetInstId(TryEvalInst( - context, SemIR::InstId::None, - SemIR::SpecificFunction{ - .type_id = GetSingletonType( - context, SemIR::SpecificFunctionType::SingletonInstId), - .callee_id = generic.decl_id, - .specific_id = specific_id})); - } - case SemIR::AssociatedConstantDecl::Kind: { - // TODO: We don't have a good instruction to use here. - return generic.decl_id; - } - default: { - CARBON_FATAL("Unknown kind for generic declaration {0}", decl); - } - } -} - auto DiagnoseIfGenericMissingExplicitParameters( Context& context, SemIR::EntityWithParamsBase& entity_base) -> void { if (!entity_base.implicit_param_patterns_id.has_value() || diff --git a/toolchain/check/generic.h b/toolchain/check/generic.h index 22f2884236ae..9abfcb511a4d 100644 --- a/toolchain/check/generic.h +++ b/toolchain/check/generic.h @@ -82,11 +82,6 @@ auto ResolveSpecificDeclaration(Context& context, SemIRLoc loc, auto ResolveSpecificDefinition(Context& context, SemIRLoc loc, SemIR::SpecificId specific_id) -> bool; -// Returns an instruction describing the entity named by the given specific. -// This is used to name the entity in diagnostics. -auto GetInstForSpecific(Context& context, SemIR::SpecificId specific_id) - -> SemIR::InstId; - // Diagnoses if an entity has implicit parameters, indicating it's generic, but // is missing explicit parameters. auto DiagnoseIfGenericMissingExplicitParameters( diff --git a/toolchain/check/name_lookup.cpp b/toolchain/check/name_lookup.cpp index c3f057a6d038..edeb8bd5720d 100644 --- a/toolchain/check/name_lookup.cpp +++ b/toolchain/check/name_lookup.cpp @@ -349,17 +349,23 @@ static auto DiagnoseMemberNameNotFound( llvm::ArrayRef lookup_scopes) -> void { if (lookup_scopes.size() == 1 && lookup_scopes.front().name_scope_id.has_value()) { - auto specific_id = lookup_scopes.front().specific_id; - auto scope_inst_id = specific_id.has_value() - ? GetInstForSpecific(context, specific_id) - : context.name_scopes() - .Get(lookup_scopes.front().name_scope_id) - .inst_id(); - CARBON_DIAGNOSTIC(MemberNameNotFoundInScope, Error, - "member name `{0}` not found in {1}", SemIR::NameId, - InstIdAsType); - context.emitter().Emit(loc, MemberNameNotFoundInScope, name_id, - scope_inst_id); + if (auto specific_id = lookup_scopes.front().specific_id; + specific_id.has_value()) { + CARBON_DIAGNOSTIC(MemberNameNotFoundInSpecificScope, Error, + "member name `{0}` not found in {1}", SemIR::NameId, + SemIR::SpecificId); + context.emitter().Emit(loc, MemberNameNotFoundInSpecificScope, name_id, + specific_id); + } else { + auto scope_inst_id = context.name_scopes() + .Get(lookup_scopes.front().name_scope_id) + .inst_id(); + CARBON_DIAGNOSTIC(MemberNameNotFoundInInstScope, Error, + "member name `{0}` not found in {1}", SemIR::NameId, + InstIdAsType); + context.emitter().Emit(loc, MemberNameNotFoundInInstScope, name_id, + scope_inst_id); + } return; } diff --git a/toolchain/check/sem_ir_loc_diagnostic_emitter.cpp b/toolchain/check/sem_ir_loc_diagnostic_emitter.cpp index d0c7b05f38a0..b4bdf525ffec 100644 --- a/toolchain/check/sem_ir_loc_diagnostic_emitter.cpp +++ b/toolchain/check/sem_ir_loc_diagnostic_emitter.cpp @@ -114,6 +114,9 @@ auto SemIRLocDiagnosticEmitter::ConvertArg(llvm::Any arg) const -> llvm::Any { StringifyTypeExpr(*sem_ir_, sem_ir_->types().GetInstId(*type_id)) + "`"; } + if (auto* specific_id = llvm::any_cast(&arg)) { + return "`" + StringifySpecific(*sem_ir_, *specific_id) + "`"; + } if (auto* typed_int = llvm::any_cast(&arg)) { return llvm::APSInt(typed_int->value, !sem_ir_->types().IsSignedInt(typed_int->type)); diff --git a/toolchain/check/testdata/alias/no_prelude/fail_local_in_namespace.carbon b/toolchain/check/testdata/alias/no_prelude/fail_local_in_namespace.carbon index 286e74b5884e..3cb22cdb38f9 100644 --- a/toolchain/check/testdata/alias/no_prelude/fail_local_in_namespace.carbon +++ b/toolchain/check/testdata/alias/no_prelude/fail_local_in_namespace.carbon @@ -20,7 +20,7 @@ fn F() -> {} { // CHECK:STDERR: ^~ // CHECK:STDERR: alias NS.a = {}; - // CHECK:STDERR: fail_local_in_namespace.carbon:[[@LINE+4]]:10: error: member name `a` not found in `NS` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_local_in_namespace.carbon:[[@LINE+4]]:10: error: member name `a` not found in `NS` [MemberNameNotFoundInInstScope] // CHECK:STDERR: return NS.a; // CHECK:STDERR: ^~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/alias/no_prelude/import_access.carbon b/toolchain/check/testdata/alias/no_prelude/import_access.carbon index f4ae95d08465..31e91b4b9767 100644 --- a/toolchain/check/testdata/alias/no_prelude/import_access.carbon +++ b/toolchain/check/testdata/alias/no_prelude/import_access.carbon @@ -47,7 +47,7 @@ package Other library "[[@TEST_NAME]]"; import Test library "def"; -// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:11: error: member name `A` not found in `Test` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:11: error: member name `A` not found in `Test` [MemberNameNotFoundInInstScope] // CHECK:STDERR: var inst: Test.A = {}; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/class/adapter/adapt.carbon b/toolchain/check/testdata/class/adapter/adapt.carbon index 03bf06080e61..b765050ab8fa 100644 --- a/toolchain/check/testdata/class/adapter/adapt.carbon +++ b/toolchain/check/testdata/class/adapter/adapt.carbon @@ -39,7 +39,7 @@ class AdaptNotExtend { fn F(a: AdaptNotExtend) { // `Adapted` is not extended, so lookup for `F` finds nothing. - // CHECK:STDERR: fail_not_extend.carbon:[[@LINE+4]]:3: error: member name `F` not found in `AdaptNotExtend` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_not_extend.carbon:[[@LINE+4]]:3: error: member name `F` not found in `AdaptNotExtend` [MemberNameNotFoundInInstScope] // CHECK:STDERR: a.F(); // CHECK:STDERR: ^~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/class/adapter/extend_adapt.carbon b/toolchain/check/testdata/class/adapter/extend_adapt.carbon index d38b792a58fc..46e705dc7b4a 100644 --- a/toolchain/check/testdata/class/adapter/extend_adapt.carbon +++ b/toolchain/check/testdata/class/adapter/extend_adapt.carbon @@ -95,7 +95,7 @@ class StructAdapter { fn F(a: StructAdapter) -> i32 { // TODO: This should be allowed. - // CHECK:STDERR: fail_todo_adapt_struct.carbon:[[@LINE+4]]:10: error: member name `b` not found in `StructAdapter` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_todo_adapt_struct.carbon:[[@LINE+4]]:10: error: member name `b` not found in `StructAdapter` [MemberNameNotFoundInInstScope] // CHECK:STDERR: return a.b; // CHECK:STDERR: ^~~ // CHECK:STDERR: @@ -131,7 +131,7 @@ class IntAdapter { fn F(a: IntAdapter) -> i32 { // Builtin types have no member names. - // CHECK:STDERR: fail_adapt_builtin.carbon:[[@LINE+4]]:10: error: member name `foo` not found in `IntAdapter` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_adapt_builtin.carbon:[[@LINE+4]]:10: error: member name `foo` not found in `IntAdapter` [MemberNameNotFoundInInstScope] // CHECK:STDERR: return a.foo; // CHECK:STDERR: ^~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/class/adapter/fail_adapt_bad_decl.carbon b/toolchain/check/testdata/class/adapter/fail_adapt_bad_decl.carbon index a2662ce85b69..dd23a0b871ca 100644 --- a/toolchain/check/testdata/class/adapter/fail_adapt_bad_decl.carbon +++ b/toolchain/check/testdata/class/adapter/fail_adapt_bad_decl.carbon @@ -23,7 +23,7 @@ class Bad { adapt 100; } -// CHECK:STDERR: fail_not_type.carbon:[[@LINE+4]]:18: error: member name `F` not found in `Bad` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_not_type.carbon:[[@LINE+4]]:18: error: member name `F` not found in `Bad` [MemberNameNotFoundInInstScope] // CHECK:STDERR: fn Use(b: Bad) { b.F(); } // CHECK:STDERR: ^~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/class/fail_base_bad_type.carbon b/toolchain/check/testdata/class/fail_base_bad_type.carbon index 9d6de7768456..662aff4d8372 100644 --- a/toolchain/check/testdata/class/fail_base_bad_type.carbon +++ b/toolchain/check/testdata/class/fail_base_bad_type.carbon @@ -56,7 +56,7 @@ class DeriveFromi32 { // but it shouldn't crash. fn ConvertToBadBasei32(p: DeriveFromi32*) -> i32* { return p; } -// CHECK:STDERR: fail_derive_from_i32.carbon:[[@LINE+4]]:70: error: member name `n` not found in `DeriveFromi32` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_derive_from_i32.carbon:[[@LINE+4]]:70: error: member name `n` not found in `DeriveFromi32` [MemberNameNotFoundInInstScope] // CHECK:STDERR: fn AccessMemberWithInvalidBasei32(p: DeriveFromi32*) -> i32 { return (*p).n; } // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: @@ -171,7 +171,7 @@ fn AccessMemberWithInvalidBaseFinal_WithMember(p: DeriveFromFinal*) -> i32 { } fn AccessMemberWithInvalidBaseFinal_NoMember(p: DeriveFromFinal*) -> i32 { - // CHECK:STDERR: fail_derive_from_final.carbon:[[@LINE+4]]:10: error: member name `b` not found in `DeriveFromFinal` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_derive_from_final.carbon:[[@LINE+4]]:10: error: member name `b` not found in `DeriveFromFinal` [MemberNameNotFoundInInstScope] // CHECK:STDERR: return (*p).b; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/class/fail_unknown_member.carbon b/toolchain/check/testdata/class/fail_unknown_member.carbon index 35dfded8abb5..236794e00ed3 100644 --- a/toolchain/check/testdata/class/fail_unknown_member.carbon +++ b/toolchain/check/testdata/class/fail_unknown_member.carbon @@ -14,7 +14,7 @@ class Class { fn G(c: Class) -> i32 { // TODO: Mention the scope in which we looked for the name. - // CHECK:STDERR: fail_unknown_member.carbon:[[@LINE+4]]:10: error: member name `something` not found in `Class` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_unknown_member.carbon:[[@LINE+4]]:10: error: member name `something` not found in `Class` [MemberNameNotFoundInInstScope] // CHECK:STDERR: return c.something; // CHECK:STDERR: ^~~~~~~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/class/generic/member_lookup.carbon b/toolchain/check/testdata/class/generic/member_lookup.carbon index e4d88724ce3c..dbdd40c6b664 100644 --- a/toolchain/check/testdata/class/generic/member_lookup.carbon +++ b/toolchain/check/testdata/class/generic/member_lookup.carbon @@ -47,7 +47,7 @@ class Derived(T:! type) { } fn AccessMissingBase[T:! type](x: Base(T)) -> T { - // CHECK:STDERR: fail_no_member.carbon:[[@LINE+4]]:10: error: member name `nonesuch` not found in `Base(T)` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_no_member.carbon:[[@LINE+4]]:10: error: member name `nonesuch` not found in `Base(T)` [MemberNameNotFoundInSpecificScope] // CHECK:STDERR: return x.nonesuch; // CHECK:STDERR: ^~~~~~~~~~ // CHECK:STDERR: @@ -55,7 +55,7 @@ fn AccessMissingBase[T:! type](x: Base(T)) -> T { } fn AccessMissingDerived[T:! type](x: Derived(T)) -> T { - // CHECK:STDERR: fail_no_member.carbon:[[@LINE+4]]:10: error: member name `nonesuch` not found in `Derived(T)` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_no_member.carbon:[[@LINE+4]]:10: error: member name `nonesuch` not found in `Derived(T)` [MemberNameNotFoundInSpecificScope] // CHECK:STDERR: return x.nonesuch; // CHECK:STDERR: ^~~~~~~~~~ // CHECK:STDERR: @@ -63,7 +63,7 @@ fn AccessMissingDerived[T:! type](x: Derived(T)) -> T { } fn AccessMissingConcrete(x: Derived(i32)) -> i32 { - // CHECK:STDERR: fail_no_member.carbon:[[@LINE+4]]:10: error: member name `nonesuch` not found in `Derived(i32)` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_no_member.carbon:[[@LINE+4]]:10: error: member name `nonesuch` not found in `Derived(i32)` [MemberNameNotFoundInSpecificScope] // CHECK:STDERR: return x.nonesuch; // CHECK:STDERR: ^~~~~~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/class/no_prelude/import_access.carbon b/toolchain/check/testdata/class/no_prelude/import_access.carbon index 9cd92aff6837..52ea8bbb6aed 100644 --- a/toolchain/check/testdata/class/no_prelude/import_access.carbon +++ b/toolchain/check/testdata/class/no_prelude/import_access.carbon @@ -60,7 +60,7 @@ package Other library "[[@TEST_NAME]]"; import Test library "def"; -// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:8: error: member name `Def` not found in `Test` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:8: error: member name `Def` not found in `Test` [MemberNameNotFoundInInstScope] // CHECK:STDERR: var c: Test.Def = {}; // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: @@ -90,7 +90,7 @@ package Other library "[[@TEST_NAME]]"; import Test library "forward_with_def"; -// CHECK:STDERR: fail_other_forward_with_def.carbon:[[@LINE+4]]:8: error: member name `ForwardWithDef` not found in `Test` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_other_forward_with_def.carbon:[[@LINE+4]]:8: error: member name `ForwardWithDef` not found in `Test` [MemberNameNotFoundInInstScope] // CHECK:STDERR: var c: Test.ForwardWithDef = {}; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -122,7 +122,7 @@ package Other library "[[@TEST_NAME]]"; import Test library "forward"; -// CHECK:STDERR: fail_other_forward.carbon:[[@LINE+4]]:9: error: member name `Forward` not found in `Test` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_other_forward.carbon:[[@LINE+4]]:9: error: member name `Forward` not found in `Test` [MemberNameNotFoundInInstScope] // CHECK:STDERR: fn F(c: Test.Forward*) {} // CHECK:STDERR: ^~~~~~~~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/class/no_prelude/name_poisoning.carbon b/toolchain/check/testdata/class/no_prelude/name_poisoning.carbon index 7a022343becc..56a585cef001 100644 --- a/toolchain/check/testdata/class/no_prelude/name_poisoning.carbon +++ b/toolchain/check/testdata/class/no_prelude/name_poisoning.carbon @@ -67,7 +67,7 @@ namespace N; fn N.F1() -> C; // Use `N.C` which was poisoned and not declared. -// CHECK:STDERR: fail_use_poison.carbon:[[@LINE+4]]:14: error: member name `C` not found in `N` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_use_poison.carbon:[[@LINE+4]]:14: error: member name `C` not found in `N` [MemberNameNotFoundInInstScope] // CHECK:STDERR: fn N.F2() -> N.C; // CHECK:STDERR: ^~~ // CHECK:STDERR: @@ -94,7 +94,7 @@ fn N.F1(x: C); class N.C; // Failure: `N.C` used after declaration failed. -// CHECK:STDERR: fail_use_declaration_after_poison.carbon:[[@LINE+4]]:12: error: member name `C` not found in `N` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_use_declaration_after_poison.carbon:[[@LINE+4]]:12: error: member name `C` not found in `N` [MemberNameNotFoundInInstScope] // CHECK:STDERR: fn N.F2(x: N.C); // CHECK:STDERR: ^~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/function/declaration/no_prelude/name_poisoning.carbon b/toolchain/check/testdata/function/declaration/no_prelude/name_poisoning.carbon index e20fdadda425..ff021d73f946 100644 --- a/toolchain/check/testdata/function/declaration/no_prelude/name_poisoning.carbon +++ b/toolchain/check/testdata/function/declaration/no_prelude/name_poisoning.carbon @@ -69,7 +69,7 @@ fn F1(); namespace N; alias N.F2 = F1; -// CHECK:STDERR: fail_use_poison.carbon:[[@LINE+4]]:14: error: member name `F1` not found in `N` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_use_poison.carbon:[[@LINE+4]]:14: error: member name `F1` not found in `N` [MemberNameNotFoundInInstScope] // CHECK:STDERR: alias N.F3 = N.F1; // CHECK:STDERR: ^~~~ // CHECK:STDERR: @@ -97,7 +97,7 @@ fn N.F1(); // Failure: `N.F1` used after declaration failed. // TODO: #4622 - Allow defining a poisoned name so it would be found if used after it's declared. -// CHECK:STDERR: fail_use_declaration_after_poison.carbon:[[@LINE+4]]:14: error: member name `F1` not found in `N` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_use_declaration_after_poison.carbon:[[@LINE+4]]:14: error: member name `F1` not found in `N` [MemberNameNotFoundInInstScope] // CHECK:STDERR: alias N.F3 = N.F1; // CHECK:STDERR: ^~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/function/definition/import_access.carbon b/toolchain/check/testdata/function/definition/import_access.carbon index fd9ded7bb48c..dab03e195478 100644 --- a/toolchain/check/testdata/function/definition/import_access.carbon +++ b/toolchain/check/testdata/function/definition/import_access.carbon @@ -60,7 +60,7 @@ package Other library "[[@TEST_NAME]]"; import Test library "def"; -// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:13: error: member name `Def` not found in `Test` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:13: error: member name `Def` not found in `Test` [MemberNameNotFoundInInstScope] // CHECK:STDERR: var f: () = Test.Def(); // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: @@ -90,7 +90,7 @@ package Other library "[[@TEST_NAME]]"; import Test library "forward_with_def"; -// CHECK:STDERR: fail_other_forward_with_def.carbon:[[@LINE+4]]:13: error: member name `ForwardWithDef` not found in `Test` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_other_forward_with_def.carbon:[[@LINE+4]]:13: error: member name `ForwardWithDef` not found in `Test` [MemberNameNotFoundInInstScope] // CHECK:STDERR: var f: () = Test.ForwardWithDef(); // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -122,7 +122,7 @@ package Other library "[[@TEST_NAME]]"; import Test library "forward"; -// CHECK:STDERR: fail_other_forward.carbon:[[@LINE+4]]:13: error: member name `Forward` not found in `Test` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_other_forward.carbon:[[@LINE+4]]:13: error: member name `Forward` not found in `Test` [MemberNameNotFoundInInstScope] // CHECK:STDERR: var f: () = Test.Forward(); // CHECK:STDERR: ^~~~~~~~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/generic/template/member_access.carbon b/toolchain/check/testdata/generic/template/member_access.carbon index a15eec9a1283..4fd6ba141079 100644 --- a/toolchain/check/testdata/generic/template/member_access.carbon +++ b/toolchain/check/testdata/generic/template/member_access.carbon @@ -33,7 +33,7 @@ fn Test2(x: {.m: i32, .n: i32}) { library "[[@TEST_NAME]]"; fn F[template T:! type](x: T) -> i32 { - // CHECK:STDERR: fail_no_such_member.carbon:[[@LINE+3]]:10: error: member name `n` not found in `D` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_no_such_member.carbon:[[@LINE+3]]:10: error: member name `n` not found in `D` [MemberNameNotFoundInInstScope] // CHECK:STDERR: return x.n; // CHECK:STDERR: ^~~ return x.n; diff --git a/toolchain/check/testdata/interface/member_lookup.carbon b/toolchain/check/testdata/interface/member_lookup.carbon index 528c8ad4e411..d082e0101c70 100644 --- a/toolchain/check/testdata/interface/member_lookup.carbon +++ b/toolchain/check/testdata/interface/member_lookup.carbon @@ -33,7 +33,7 @@ interface Interface(T:! type) { } fn AccessMissingGeneric[T:! type](I:! Interface(T)) -> T { - // CHECK:STDERR: fail_no_member.carbon:[[@LINE+4]]:10: error: member name `nonesuch` not found in `Interface(T)` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_no_member.carbon:[[@LINE+4]]:10: error: member name `nonesuch` not found in `Interface(T)` [MemberNameNotFoundInSpecificScope] // CHECK:STDERR: return I.nonesuch; // CHECK:STDERR: ^~~~~~~~~~ // CHECK:STDERR: @@ -41,7 +41,7 @@ fn AccessMissingGeneric[T:! type](I:! Interface(T)) -> T { } fn AccessMissingConcrete(I:! Interface(i32)) -> i32 { - // CHECK:STDERR: fail_no_member.carbon:[[@LINE+4]]:10: error: member name `nonesuch` not found in `Interface(i32)` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_no_member.carbon:[[@LINE+4]]:10: error: member name `nonesuch` not found in `Interface(i32)` [MemberNameNotFoundInSpecificScope] // CHECK:STDERR: return I.nonesuch; // CHECK:STDERR: ^~~~~~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/interface/no_prelude/import_access.carbon b/toolchain/check/testdata/interface/no_prelude/import_access.carbon index 7e46a966b92d..27656a6795d6 100644 --- a/toolchain/check/testdata/interface/no_prelude/import_access.carbon +++ b/toolchain/check/testdata/interface/no_prelude/import_access.carbon @@ -61,7 +61,7 @@ package Other library "[[@TEST_NAME]]"; import Test library "def"; -// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:9: error: member name `Def` not found in `Test` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:9: error: member name `Def` not found in `Test` [MemberNameNotFoundInInstScope] // CHECK:STDERR: fn F(i: Test.Def) {} // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: @@ -91,7 +91,7 @@ package Other library "[[@TEST_NAME]]"; import Test library "forward_with_def"; -// CHECK:STDERR: fail_other_forward_with_def.carbon:[[@LINE+4]]:9: error: member name `ForwardWithDef` not found in `Test` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_other_forward_with_def.carbon:[[@LINE+4]]:9: error: member name `ForwardWithDef` not found in `Test` [MemberNameNotFoundInInstScope] // CHECK:STDERR: fn F(i: Test.ForwardWithDef) {} // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/interface/no_prelude/name_poisoning.carbon b/toolchain/check/testdata/interface/no_prelude/name_poisoning.carbon index bb426a33453b..57255206b1f7 100644 --- a/toolchain/check/testdata/interface/no_prelude/name_poisoning.carbon +++ b/toolchain/check/testdata/interface/no_prelude/name_poisoning.carbon @@ -66,7 +66,7 @@ namespace N; // Use `package.I` and poison `N.I`. fn N.F1(x:! I); -// CHECK:STDERR: fail_use_poison.carbon:[[@LINE+4]]:13: error: member name `I` not found in `N` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_use_poison.carbon:[[@LINE+4]]:13: error: member name `I` not found in `N` [MemberNameNotFoundInInstScope] // CHECK:STDERR: fn N.F2(x:! N.I); // CHECK:STDERR: ^~~ // CHECK:STDERR: @@ -91,7 +91,7 @@ fn N.F1(x:! I); // CHECK:STDERR: interface N.I; -// CHECK:STDERR: fail_use_declaration_after_poison.carbon:[[@LINE+4]]:13: error: member name `I` not found in `N` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_use_declaration_after_poison.carbon:[[@LINE+4]]:13: error: member name `I` not found in `N` [MemberNameNotFoundInInstScope] // CHECK:STDERR: fn N.F2(x:! N.I); // CHECK:STDERR: ^~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/interop/cpp/no_prelude/function_decl.carbon b/toolchain/check/testdata/interop/cpp/no_prelude/function_decl.carbon index 61679f6cd1f8..6751ffa56f68 100644 --- a/toolchain/check/testdata/interop/cpp/no_prelude/function_decl.carbon +++ b/toolchain/check/testdata/interop/cpp/no_prelude/function_decl.carbon @@ -29,7 +29,7 @@ library "[[@TEST_NAME]]"; import Cpp library "function_decl.h"; fn MyF() { - // CHECK:STDERR: fail_import_function_decl_use_different_name.carbon:[[@LINE+4]]:3: error: member name `bar` not found in `Cpp` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_import_function_decl_use_different_name.carbon:[[@LINE+4]]:3: error: member name `bar` not found in `Cpp` [MemberNameNotFoundInInstScope] // CHECK:STDERR: Cpp.bar(); // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: @@ -47,7 +47,7 @@ library "[[@TEST_NAME]]"; import Cpp library "function_special_name_decl.h"; fn MyF() { - // CHECK:STDERR: fail_import_function_special_name_decl.carbon:[[@LINE+4]]:3: error: member name `base` not found in `Cpp` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_import_function_special_name_decl.carbon:[[@LINE+4]]:3: error: member name `base` not found in `Cpp` [MemberNameNotFoundInInstScope] // CHECK:STDERR: Cpp.base(); // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/interop/cpp/no_prelude/namespace.carbon b/toolchain/check/testdata/interop/cpp/no_prelude/namespace.carbon index 4075777617bb..cab8ae072778 100644 --- a/toolchain/check/testdata/interop/cpp/no_prelude/namespace.carbon +++ b/toolchain/check/testdata/interop/cpp/no_prelude/namespace.carbon @@ -53,7 +53,7 @@ library "[[@TEST_NAME]]"; import Cpp library "namespace.h"; fn MyF() { - // CHECK:STDERR: fail_import_namespace_wrong_name_in_namespace.carbon:[[@LINE+4]]:3: error: member name `not_foo` not found in `Cpp.my_namespace` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_import_namespace_wrong_name_in_namespace.carbon:[[@LINE+4]]:3: error: member name `not_foo` not found in `Cpp.my_namespace` [MemberNameNotFoundInInstScope] // CHECK:STDERR: Cpp.my_namespace.not_foo(); // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -67,7 +67,7 @@ library "[[@TEST_NAME]]"; import Cpp library "namespace.h"; fn MyF() { - // CHECK:STDERR: fail_import_namespace_use_different_name.carbon:[[@LINE+4]]:3: error: member name `not_my_namespace` not found in `Cpp` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_import_namespace_use_different_name.carbon:[[@LINE+4]]:3: error: member name `not_my_namespace` not found in `Cpp` [MemberNameNotFoundInInstScope] // CHECK:STDERR: Cpp.not_my_namespace.foo(); // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -85,7 +85,7 @@ library "[[@TEST_NAME]]"; import Cpp library "namespace_special_name_decl.h"; fn MyF() { - // CHECK:STDERR: fail_import_namespace_special_name_decl.carbon:[[@LINE+4]]:3: error: member name `base` not found in `Cpp` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_import_namespace_special_name_decl.carbon:[[@LINE+4]]:3: error: member name `base` not found in `Cpp` [MemberNameNotFoundInInstScope] // CHECK:STDERR: Cpp.base.foo(); // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/interop/cpp/no_prelude/unsupported_decl_type.carbon b/toolchain/check/testdata/interop/cpp/no_prelude/unsupported_decl_type.carbon index edbdc74a5349..0195eafeebaf 100644 --- a/toolchain/check/testdata/interop/cpp/no_prelude/unsupported_decl_type.carbon +++ b/toolchain/check/testdata/interop/cpp/no_prelude/unsupported_decl_type.carbon @@ -26,7 +26,7 @@ fn F() { // CHECK:STDERR: Cpp.foo(); // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: - // CHECK:STDERR: fail_import_unsupported_decl.carbon:[[@LINE+4]]:3: error: member name `foo` not found in `Cpp` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_import_unsupported_decl.carbon:[[@LINE+4]]:3: error: member name `foo` not found in `Cpp` [MemberNameNotFoundInInstScope] // CHECK:STDERR: Cpp.foo(); // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/let/no_prelude/import_access.carbon b/toolchain/check/testdata/let/no_prelude/import_access.carbon index 51eee19d06c1..528e6ba17bae 100644 --- a/toolchain/check/testdata/let/no_prelude/import_access.carbon +++ b/toolchain/check/testdata/let/no_prelude/import_access.carbon @@ -46,7 +46,7 @@ package Other library "[[@TEST_NAME]]"; import Test library "def"; -// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:14: error: member name `v` not found in `Test` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:14: error: member name `v` not found in `Test` [MemberNameNotFoundInInstScope] // CHECK:STDERR: let v2: () = Test.v; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/namespace/no_prelude/name_poisoning.carbon b/toolchain/check/testdata/namespace/no_prelude/name_poisoning.carbon index 2b9e7f14a128..9f8bc4a06487 100644 --- a/toolchain/check/testdata/namespace/no_prelude/name_poisoning.carbon +++ b/toolchain/check/testdata/namespace/no_prelude/name_poisoning.carbon @@ -68,7 +68,7 @@ namespace N1; namespace N2; alias N2.N3 = N1; -// CHECK:STDERR: fail_use_poison.carbon:[[@LINE+4]]:15: error: member name `N1` not found in `N2` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_use_poison.carbon:[[@LINE+4]]:15: error: member name `N1` not found in `N2` [MemberNameNotFoundInInstScope] // CHECK:STDERR: alias N2.N4 = N2.N1; // CHECK:STDERR: ^~~~~ // CHECK:STDERR: @@ -94,7 +94,7 @@ alias N2.N3 = N1; // CHECK:STDERR: namespace N2.N1; -// CHECK:STDERR: fail_use_declaration_after_poison.carbon:[[@LINE+4]]:15: error: member name `N1` not found in `N2` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_use_declaration_after_poison.carbon:[[@LINE+4]]:15: error: member name `N1` not found in `N2` [MemberNameNotFoundInInstScope] // CHECK:STDERR: alias N2.N4 = N2.N1; // CHECK:STDERR: ^~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/package_expr/fail_not_found.carbon b/toolchain/check/testdata/package_expr/fail_not_found.carbon index 4b77533a0afb..59b8074aeace 100644 --- a/toolchain/check/testdata/package_expr/fail_not_found.carbon +++ b/toolchain/check/testdata/package_expr/fail_not_found.carbon @@ -9,7 +9,7 @@ // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/package_expr/fail_not_found.carbon fn Main() { - // CHECK:STDERR: fail_not_found.carbon:[[@LINE+4]]:16: error: member name `x` not found in `package` [MemberNameNotFoundInScope] + // CHECK:STDERR: fail_not_found.carbon:[[@LINE+4]]:16: error: member name `x` not found in `package` [MemberNameNotFoundInInstScope] // CHECK:STDERR: var y: i32 = package.x; // CHECK:STDERR: ^~~~~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/packages/no_prelude/cross_package_import.carbon b/toolchain/check/testdata/packages/no_prelude/cross_package_import.carbon index 366d2181b23e..86ace6cf497d 100644 --- a/toolchain/check/testdata/packages/no_prelude/cross_package_import.carbon +++ b/toolchain/check/testdata/packages/no_prelude/cross_package_import.carbon @@ -201,7 +201,7 @@ library "[[@TEST_NAME]]"; import Other library "other_fn_use"; -// CHECK:STDERR: fail_use_other_fn_use.carbon:[[@LINE+4]]:13: error: member name `F` not found in `Other` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_use_other_fn_use.carbon:[[@LINE+4]]:13: error: member name `F` not found in `Other` [MemberNameNotFoundInInstScope] // CHECK:STDERR: fn UseF() { Other.F(); } // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/packages/raw_core.carbon b/toolchain/check/testdata/packages/raw_core.carbon index cb27534e2c09..00006d78e108 100644 --- a/toolchain/check/testdata/packages/raw_core.carbon +++ b/toolchain/check/testdata/packages/raw_core.carbon @@ -30,13 +30,13 @@ library "[[@TEST_NAME]]"; import r#Core; -// CHECK:STDERR: fail_raw_core_not_core.carbon:[[@LINE+4]]:10: error: member name `F` not found in `Core` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_raw_core_not_core.carbon:[[@LINE+4]]:10: error: member name `F` not found in `Core` [MemberNameNotFoundInInstScope] // CHECK:STDERR: fn G() { Core.F(); } // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: fn G() { Core.F(); } -// CHECK:STDERR: fail_raw_core_not_core.carbon:[[@LINE+4]]:10: error: member name `Int` not found in `r#Core` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_raw_core_not_core.carbon:[[@LINE+4]]:10: error: member name `Int` not found in `r#Core` [MemberNameNotFoundInInstScope] // CHECK:STDERR: fn H() { r#Core.Int(32); } // CHECK:STDERR: ^~~~~~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/var/no_prelude/import_access.carbon b/toolchain/check/testdata/var/no_prelude/import_access.carbon index 454cf569c7a9..4e33d4b9dfc8 100644 --- a/toolchain/check/testdata/var/no_prelude/import_access.carbon +++ b/toolchain/check/testdata/var/no_prelude/import_access.carbon @@ -46,7 +46,7 @@ package Other library "[[@TEST_NAME]]"; import Test library "def"; -// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:14: error: member name `v` not found in `Test` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_other_def.carbon:[[@LINE+4]]:14: error: member name `v` not found in `Test` [MemberNameNotFoundInInstScope] // CHECK:STDERR: var v2: () = Test.v; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/where_expr/designator.carbon b/toolchain/check/testdata/where_expr/designator.carbon index 5152b706f1ba..28526523ec6f 100644 --- a/toolchain/check/testdata/where_expr/designator.carbon +++ b/toolchain/check/testdata/where_expr/designator.carbon @@ -30,7 +30,7 @@ interface J { let Member:! type; } -// CHECK:STDERR: fail_wrong_member.carbon:[[@LINE+4]]:31: error: member name `Mismatch` not found in `J` [MemberNameNotFoundInScope] +// CHECK:STDERR: fail_wrong_member.carbon:[[@LINE+4]]:31: error: member name `Mismatch` not found in `J` [MemberNameNotFoundInInstScope] // CHECK:STDERR: fn PeriodMismatch(W:! J where .Mismatch = {}); // CHECK:STDERR: ^~~~~~~~~ // CHECK:STDERR: diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index 4781de1d59c1..188940764576 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -329,7 +329,8 @@ CARBON_DIAGNOSTIC_KIND(InNameLookup) CARBON_DIAGNOSTIC_KIND(NameAmbiguousDueToExtend) CARBON_DIAGNOSTIC_KIND(NameNotFound) CARBON_DIAGNOSTIC_KIND(MemberNameNotFound) -CARBON_DIAGNOSTIC_KIND(MemberNameNotFoundInScope) +CARBON_DIAGNOSTIC_KIND(MemberNameNotFoundInInstScope) +CARBON_DIAGNOSTIC_KIND(MemberNameNotFoundInSpecificScope) CARBON_DIAGNOSTIC_KIND(NoPeriodSelfForDesignator) CARBON_DIAGNOSTIC_KIND(UsedBeforeInitialization) diff --git a/toolchain/sem_ir/ids.h b/toolchain/sem_ir/ids.h index 0379546318c8..b6f344f4649b 100644 --- a/toolchain/sem_ir/ids.h +++ b/toolchain/sem_ir/ids.h @@ -301,6 +301,8 @@ struct GenericId : public IdBase { // The ID of a specific, which is the result of specifying the generic arguments // for a generic. struct SpecificId : public IdBase { + using DiagnosticType = Diagnostics::TypeInfo; + static constexpr llvm::StringLiteral Label = "specific"; using ValueType = Specific; diff --git a/toolchain/sem_ir/stringify_type.cpp b/toolchain/sem_ir/stringify_type.cpp index 1e322385deeb..997bd2388566 100644 --- a/toolchain/sem_ir/stringify_type.cpp +++ b/toolchain/sem_ir/stringify_type.cpp @@ -59,10 +59,7 @@ class StepStack { // Starts a new stack, which always contains the first instruction to // stringify. - explicit StepStack(const SemIR::File* file, InstId outer_inst_id) - : sem_ir_(file) { - PushInstId(outer_inst_id); - } + explicit StepStack(const SemIR::File* file) : sem_ir_(file) {} // These push basic entries onto the stack. auto PushInstId(InstId inst_id) -> void { steps_.push_back(inst_id); } @@ -608,13 +605,10 @@ class Stringifier { } // namespace -auto StringifyTypeExpr(const SemIR::File& sem_ir, InstId outer_inst_id) +static auto Stringify(const SemIR::File& sem_ir, StepStack& step_stack) -> std::string { RawStringOstream out; - // Note: Since this is a stack, work is resolved in the reverse order from the - // order pushed. - StepStack step_stack(&sem_ir, outer_inst_id); Stringifier stringifier(&sem_ir, &step_stack, &out); while (!step_stack.empty()) { @@ -645,4 +639,60 @@ auto StringifyTypeExpr(const SemIR::File& sem_ir, InstId outer_inst_id) return out.TakeStr(); } +auto StringifyTypeExpr(const SemIR::File& sem_ir, InstId outer_inst_id) + -> std::string { + StepStack step_stack(&sem_ir); + step_stack.PushInstId(outer_inst_id); + return Stringify(sem_ir, step_stack); +} + +auto StringifySpecific(const File& sem_ir, SpecificId specific_id) + -> std::string { + StepStack step_stack(&sem_ir); + + const auto& specific = sem_ir.specifics().Get(specific_id); + const auto& generic = sem_ir.generics().Get(specific.generic_id); + auto decl = sem_ir.insts().Get(generic.decl_id); + CARBON_KIND_SWITCH(decl) { + case CARBON_KIND(SemIR::ClassDecl class_decl): { + // Print `Core.Int(N)` as `iN`. + // TODO: This duplicates work done in StringifyTypeInst for ClassType. + const auto& class_info = sem_ir.classes().Get(class_decl.class_id); + if (auto literal_info = NumericTypeLiteralInfo::ForType( + sem_ir, + SemIR::ClassType{.type_id = SemIR::TypeType::SingletonTypeId, + .class_id = class_decl.class_id, + .specific_id = specific_id}); + literal_info.is_valid()) { + RawStringOstream out; + literal_info.PrintLiteral(sem_ir, out); + return out.TakeStr(); + } + step_stack.PushEntityName(class_info, specific_id); + break; + } + case CARBON_KIND(SemIR::FunctionDecl function_decl): { + step_stack.PushEntityName( + sem_ir.functions().Get(function_decl.function_id), specific_id); + break; + } + case CARBON_KIND(SemIR::ImplDecl impl_decl): { + step_stack.PushEntityName(sem_ir.impls().Get(impl_decl.impl_id), + specific_id); + break; + } + case CARBON_KIND(SemIR::InterfaceDecl interface_decl): { + step_stack.PushEntityName( + sem_ir.interfaces().Get(interface_decl.interface_id), specific_id); + break; + } + default: { + // TODO: Include the specific arguments here. + step_stack.PushInstId(generic.decl_id); + break; + } + } + return Stringify(sem_ir, step_stack); +} + } // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/stringify_type.h b/toolchain/sem_ir/stringify_type.h index 9c49a3fb6ae6..1484ea07a493 100644 --- a/toolchain/sem_ir/stringify_type.h +++ b/toolchain/sem_ir/stringify_type.h @@ -17,6 +17,12 @@ namespace Carbon::SemIR { // expression describing the type. auto StringifyTypeExpr(const File& sem_ir, InstId outer_inst_id) -> std::string; +// Produces a string version of the name of a specific. Generally, this should +// not be called directly. To format a string into a diagnostic, use a +// diagnostic parameter of type `SemIR::SpecificId`. +auto StringifySpecific(const File& sem_ir, SpecificId specific_id) + -> std::string; + } // namespace Carbon::SemIR #endif // CARBON_TOOLCHAIN_SEM_IR_STRINGIFY_TYPE_H_