diff --git a/toolchain/check/check.cpp b/toolchain/check/check.cpp index a70f5583f1b63..e678187108241 100644 --- a/toolchain/check/check.cpp +++ b/toolchain/check/check.cpp @@ -77,6 +77,10 @@ class SemIRLocationTranslator auto TranslateArg(DiagnosticTypeTranslation translation, llvm::Any arg) const -> llvm::Any override { switch (translation) { + case DiagnosticTypeTranslation::NameId: { + auto name_id = llvm::any_cast(arg); + return sem_ir_->names().GetFormatted(name_id).str(); + } case DiagnosticTypeTranslation::TypeId: { auto type_id = llvm::any_cast(arg); return sem_ir_->StringifyType(type_id); diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index 3adf8f3c7a18a..0a9606ebfa500 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -150,8 +150,9 @@ auto Context::DiagnoseDuplicateName(SemIR::InstId dup_def_id, auto Context::DiagnoseNameNotFound(Parse::NodeId parse_node, SemIR::NameId name_id) -> void { - CARBON_DIAGNOSTIC(NameNotFound, Error, "Name `{0}` not found.", std::string); - emitter_->Emit(parse_node, NameNotFound, names().GetFormatted(name_id).str()); + CARBON_DIAGNOSTIC(NameNotFound, Error, "Name `{0}` not found.", + SemIR::NameId); + emitter_->Emit(parse_node, NameNotFound, name_id); } auto Context::NoteIncompleteClass(SemIR::ClassId class_id, @@ -344,9 +345,8 @@ auto Context::LookupQualifiedName(Parse::NodeId parse_node, CARBON_DIAGNOSTIC( NameAmbiguousDueToExtend, Error, "Ambiguous use of name `{0}` found in multiple extended scopes.", - std::string); - emitter_->Emit(parse_node, NameAmbiguousDueToExtend, - names().GetFormatted(name_id).str()); + SemIR::NameId); + emitter_->Emit(parse_node, NameAmbiguousDueToExtend, name_id); // TODO: Add notes pointing to the scopes. return SemIR::InstId::BuiltinError; } diff --git a/toolchain/check/convert.cpp b/toolchain/check/convert.cpp index 2fe952e2eb5c7..633f706b52225 100644 --- a/toolchain/check/convert.cpp +++ b/toolchain/check/convert.cpp @@ -477,19 +477,18 @@ static auto ConvertStructToStructOrClass(Context& context, CARBON_DIAGNOSTIC( StructInitMissingFieldInLiteral, Error, "Missing value for field `{0}` in struct initialization.", - std::string); - context.emitter().Emit( - value_parse_node, StructInitMissingFieldInLiteral, - sem_ir.names().GetFormatted(dest_field.name_id).str()); + SemIR::NameId); + context.emitter().Emit(value_parse_node, + StructInitMissingFieldInLiteral, + dest_field.name_id); } else { CARBON_DIAGNOSTIC(StructInitMissingFieldInConversion, Error, "Cannot convert from struct type `{0}` to `{1}`: " "missing field `{2}` in source type.", - SemIR::TypeId, SemIR::TypeId, std::string); + SemIR::TypeId, SemIR::TypeId, SemIR::NameId); context.emitter().Emit( value_parse_node, StructInitMissingFieldInConversion, - value.type_id(), target.type_id, - sem_ir.names().GetFormatted(dest_field.name_id).str()); + value.type_id(), target.type_id, dest_field.name_id); } return SemIR::InstId::BuiltinError; } diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index 6c79a413f8014..c06b4f1da2f3c 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -129,12 +129,11 @@ auto HandleClassDefinitionStart(Context& context, // Track that this declaration is the definition. if (class_info.definition_id.is_valid()) { CARBON_DIAGNOSTIC(ClassRedefinition, Error, "Redefinition of class {0}.", - std::string); + SemIR::NameId); CARBON_DIAGNOSTIC(ClassPreviousDefinition, Note, "Previous definition was here."); context.emitter() - .Build(parse_node, ClassRedefinition, - context.names().GetFormatted(class_info.name_id).str()) + .Build(parse_node, ClassRedefinition, class_info.name_id) .Note(class_info.definition_id, ClassPreviousDefinition) .Emit(); } else { diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index e3e6c23c11b79..bd59715419255 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -206,12 +206,11 @@ auto HandleFunctionDefinitionStart(Context& context, // Track that this declaration is the definition. if (function.definition_id.is_valid()) { CARBON_DIAGNOSTIC(FunctionRedefinition, Error, - "Redefinition of function {0}.", std::string); + "Redefinition of function {0}.", SemIR::NameId); CARBON_DIAGNOSTIC(FunctionPreviousDefinition, Note, "Previous definition was here."); context.emitter() - .Build(parse_node, FunctionRedefinition, - context.names().GetFormatted(function.name_id).str()) + .Build(parse_node, FunctionRedefinition, function.name_id) .Note(function.definition_id, FunctionPreviousDefinition) .Emit(); } else { diff --git a/toolchain/check/handle_interface.cpp b/toolchain/check/handle_interface.cpp index 6bfc016a8bb42..9a916c12942f0 100644 --- a/toolchain/check/handle_interface.cpp +++ b/toolchain/check/handle_interface.cpp @@ -109,12 +109,11 @@ auto HandleInterfaceDefinitionStart( // Track that this declaration is the definition. if (interface_info.definition_id.is_valid()) { CARBON_DIAGNOSTIC(InterfaceRedefinition, Error, - "Redefinition of interface {0}.", std::string); + "Redefinition of interface {0}.", SemIR::NameId); CARBON_DIAGNOSTIC(InterfacePreviousDefinition, Note, "Previous definition was here."); context.emitter() - .Build(parse_node, InterfaceRedefinition, - context.names().GetFormatted(interface_info.name_id).str()) + .Build(parse_node, InterfaceRedefinition, interface_info.name_id) .Note(interface_info.definition_id, InterfacePreviousDefinition) .Emit(); } else { diff --git a/toolchain/check/handle_name.cpp b/toolchain/check/handle_name.cpp index 6da5d9965a1d8..3ba758c192ff7 100644 --- a/toolchain/check/handle_name.cpp +++ b/toolchain/check/handle_name.cpp @@ -223,10 +223,9 @@ auto HandleMemberAccessExpr(Context& context, } CARBON_DIAGNOSTIC(QualifiedExprNameNotFound, Error, "Type `{0}` does not have a member `{1}`.", - SemIR::TypeId, std::string); + SemIR::TypeId, SemIR::NameId); context.emitter().Emit(parse_node, QualifiedExprNameNotFound, - base_type_id, - context.names().GetFormatted(name_id).str()); + base_type_id, name_id); break; } // TODO: `ConstType` should support member access just like the diff --git a/toolchain/check/handle_struct.cpp b/toolchain/check/handle_struct.cpp index 7c6d42b61d7d0..59a75f8e50ea3 100644 --- a/toolchain/check/handle_struct.cpp +++ b/toolchain/check/handle_struct.cpp @@ -75,12 +75,12 @@ static auto DiagnoseDuplicateNames(Context& context, if (!added) { CARBON_DIAGNOSTIC(StructNameDuplicate, Error, "Duplicated field name `{1}` in {0}.", std::string, - std::string); + SemIR::NameId); CARBON_DIAGNOSTIC(StructNamePrevious, Note, "Field with the same name here."); context.emitter() .Build(field_inst_id, StructNameDuplicate, construct.str(), - sem_ir.names().GetFormatted(field_inst.name_id).str()) + field_inst.name_id) .Note(it->second, StructNamePrevious) .Emit(); return true; diff --git a/toolchain/diagnostics/diagnostic_emitter.h b/toolchain/diagnostics/diagnostic_emitter.h index 7a084e768081d..3ddd64b69bac0 100644 --- a/toolchain/diagnostics/diagnostic_emitter.h +++ b/toolchain/diagnostics/diagnostic_emitter.h @@ -141,6 +141,7 @@ class DiagnosticConsumer { // diagnostic. enum class DiagnosticTypeTranslation : int8_t { None, + NameId, TypeId, }; diff --git a/toolchain/sem_ir/ids.h b/toolchain/sem_ir/ids.h index 5f5b56b8f525d..202a17a5b3cb1 100644 --- a/toolchain/sem_ir/ids.h +++ b/toolchain/sem_ir/ids.h @@ -283,6 +283,10 @@ constexpr BoolValue BoolValue::True = BoolValue(1); // The ID of a name. A name is either a string or a special name such as // `self`, `Self`, or `base`. struct NameId : public IdBase, public Printable { + // names().GetFormatted() is used for diagnostics. + using DiagnosticType = + DiagnosticTypeInfo; + // An explicitly invalid ID. static const NameId Invalid; // The name of `self`.