diff --git a/toolchain/check/check.cpp b/toolchain/check/check.cpp index 0e06b2298c34..f47819dee2aa 100644 --- a/toolchain/check/check.cpp +++ b/toolchain/check/check.cpp @@ -72,20 +72,14 @@ class SemIRDiagnosticConverter : public DiagnosticConverter { } } - auto ConvertArg(DiagnosticTypeConversion conversion, llvm::Any arg) const - -> llvm::Any override { - switch (conversion) { - case DiagnosticTypeConversion::NameId: { - auto name_id = llvm::any_cast(arg); - return sem_ir_->names().GetFormatted(name_id).str(); - } - case DiagnosticTypeConversion::TypeId: { - auto type_id = llvm::any_cast(arg); - return sem_ir_->StringifyType(type_id); - } - default: - return DiagnosticConverter::ConvertArg(conversion, arg); + auto ConvertArg(llvm::Any arg) const -> llvm::Any override { + if (auto* name_id = llvm::any_cast(&arg)) { + return sem_ir_->names().GetFormatted(*name_id).str(); } + if (auto* type_id = llvm::any_cast(&arg)) { + return sem_ir_->StringifyType(*type_id); + } + return DiagnosticConverter::ConvertArg(arg); } private: diff --git a/toolchain/diagnostics/diagnostic_converter.h b/toolchain/diagnostics/diagnostic_converter.h index 486653116bbb..ebc28e033e3f 100644 --- a/toolchain/diagnostics/diagnostic_converter.h +++ b/toolchain/diagnostics/diagnostic_converter.h @@ -5,23 +5,11 @@ #ifndef CARBON_TOOLCHAIN_DIAGNOSTICS_DIAGNOSTIC_CONVERTER_H_ #define CARBON_TOOLCHAIN_DIAGNOSTICS_DIAGNOSTIC_CONVERTER_H_ -#include - -#include "common/check.h" #include "llvm/ADT/Any.h" #include "toolchain/diagnostics/diagnostic.h" namespace Carbon { -// Known diagnostic type conversions. These are enumerated because `llvm::Any` -// doesn't expose the contained type; instead, we infer it from a given -// diagnostic. -enum class DiagnosticTypeConversion : int8_t { - None, - NameId, - TypeId, -}; - // An interface that can convert some representation of a location into a // diagnostic location. template @@ -31,27 +19,21 @@ class DiagnosticConverter { virtual auto ConvertLocation(LocationT loc) const -> DiagnosticLocation = 0; - // Converts arg types as needed. Not all uses support conversion, so the - // default simply errors. - virtual auto ConvertArg(DiagnosticTypeConversion conversion, - llvm::Any /*arg*/) const -> llvm::Any { - CARBON_FATAL() << "Unexpected call to ConvertArg: " - << static_cast(conversion); - } + // Converts arg types as needed. Not all uses require conversion, so the + // default returns the argument unchanged. + virtual auto ConvertArg(llvm::Any arg) const -> llvm::Any { return arg; } }; -// Used by types to indicate a DiagnosticTypeConversion that results in the +// Used by types to indicate a diagnostic type conversion that results in the // provided StorageType. For example, to convert NameId to a std::string, we // write: // // struct NameId { -// using DiagnosticType = -// DiagnosticTypeInfo; +// using DiagnosticType = DiagnosticTypeInfo; // }; -template +template struct DiagnosticTypeInfo { using StorageType = StorageTypeT; - static constexpr DiagnosticTypeConversion Conversion = ConversionV; }; namespace Internal { @@ -59,13 +41,11 @@ namespace Internal { // Determines whether there's a DiagnosticType member on Arg. // Used by DiagnosticEmitter. template -concept HasDiagnosticType = - requires { std::type_identity(); }; +concept HasDiagnosticType = requires { typename Arg::DiagnosticType; }; // The default implementation with no conversion. -template -struct DiagnosticTypeForArg - : public DiagnosticTypeInfo {}; +template +struct DiagnosticTypeForArg : public DiagnosticTypeInfo {}; // Exposes a custom conversion for an argument type. template diff --git a/toolchain/diagnostics/diagnostic_emitter.h b/toolchain/diagnostics/diagnostic_emitter.h index 22c6e347f24e..c27ff91ad024 100644 --- a/toolchain/diagnostics/diagnostic_emitter.h +++ b/toolchain/diagnostics/diagnostic_emitter.h @@ -167,13 +167,12 @@ class DiagnosticEmitter { // type conversion when needed. template auto MakeAny(Arg arg) -> llvm::Any { - if constexpr (Internal::DiagnosticTypeForArg::Conversion == - DiagnosticTypeConversion::None) { - return arg; - } else { - return converter_->ConvertArg( - Internal::DiagnosticTypeForArg::Conversion, arg); - } + llvm::Any converted = converter_->ConvertArg(arg); + using Storage = Internal::DiagnosticTypeForArg::StorageType; + CARBON_CHECK(llvm::any_cast(&converted)) + << "Failed to convert argument of type " << typeid(Arg).name() + << " to its storage type " << typeid(Storage).name(); + return converted; } template diff --git a/toolchain/sem_ir/ids.h b/toolchain/sem_ir/ids.h index 2fad9f47a6c7..b1d5506f1aed 100644 --- a/toolchain/sem_ir/ids.h +++ b/toolchain/sem_ir/ids.h @@ -289,8 +289,7 @@ constexpr BoolValue BoolValue::True = BoolValue(1); // `self`, `Self`, or `base`. struct NameId : public IdBase, public Printable { // names().GetFormatted() is used for diagnostics. - using DiagnosticType = - DiagnosticTypeInfo; + using DiagnosticType = DiagnosticTypeInfo; // An explicitly invalid ID. static const NameId Invalid; @@ -427,8 +426,7 @@ constexpr InstBlockId InstBlockId::GlobalInit = InstBlockId(2); struct TypeId : public IdBase, public Printable { using ValueType = TypeInfo; // StringifyType() is used for diagnostics. - using DiagnosticType = - DiagnosticTypeInfo; + using DiagnosticType = DiagnosticTypeInfo; // The builtin TypeType. static const TypeId TypeType;