mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 10:41:03 +01:00
Simplify diagnostic conversion. (#3817)
Remove the enum of converted types, and use `llvm::any_cast` to determine the type instead.
This commit is contained in:
@@ -72,20 +72,14 @@ class SemIRDiagnosticConverter : public DiagnosticConverter<SemIRLocation> {
|
||||
}
|
||||
}
|
||||
|
||||
auto ConvertArg(DiagnosticTypeConversion conversion, llvm::Any arg) const
|
||||
-> llvm::Any override {
|
||||
switch (conversion) {
|
||||
case DiagnosticTypeConversion::NameId: {
|
||||
auto name_id = llvm::any_cast<SemIR::NameId>(arg);
|
||||
return sem_ir_->names().GetFormatted(name_id).str();
|
||||
}
|
||||
case DiagnosticTypeConversion::TypeId: {
|
||||
auto type_id = llvm::any_cast<SemIR::TypeId>(arg);
|
||||
return sem_ir_->StringifyType(type_id);
|
||||
}
|
||||
default:
|
||||
return DiagnosticConverter<SemIRLocation>::ConvertArg(conversion, arg);
|
||||
auto ConvertArg(llvm::Any arg) const -> llvm::Any override {
|
||||
if (auto* name_id = llvm::any_cast<SemIR::NameId>(&arg)) {
|
||||
return sem_ir_->names().GetFormatted(*name_id).str();
|
||||
}
|
||||
if (auto* type_id = llvm::any_cast<SemIR::TypeId>(&arg)) {
|
||||
return sem_ir_->StringifyType(*type_id);
|
||||
}
|
||||
return DiagnosticConverter<SemIRLocation>::ConvertArg(arg);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -5,23 +5,11 @@
|
||||
#ifndef CARBON_TOOLCHAIN_DIAGNOSTICS_DIAGNOSTIC_CONVERTER_H_
|
||||
#define CARBON_TOOLCHAIN_DIAGNOSTICS_DIAGNOSTIC_CONVERTER_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#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 <typename LocationT>
|
||||
@@ -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<int8_t>(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<std::string, DiagnosticTypeConversion::NameId>;
|
||||
// using DiagnosticType = DiagnosticTypeInfo<std::string>;
|
||||
// };
|
||||
template <typename StorageTypeT, DiagnosticTypeConversion ConversionV>
|
||||
template <typename StorageTypeT>
|
||||
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 <typename Arg>
|
||||
concept HasDiagnosticType =
|
||||
requires { std::type_identity<typename Arg::DiagnosticType>(); };
|
||||
concept HasDiagnosticType = requires { typename Arg::DiagnosticType; };
|
||||
|
||||
// The default implementation with no conversion.
|
||||
template <typename Arg, typename /*Unused*/ = void>
|
||||
struct DiagnosticTypeForArg
|
||||
: public DiagnosticTypeInfo<Arg, DiagnosticTypeConversion::None> {};
|
||||
template <typename Arg>
|
||||
struct DiagnosticTypeForArg : public DiagnosticTypeInfo<Arg> {};
|
||||
|
||||
// Exposes a custom conversion for an argument type.
|
||||
template <typename Arg>
|
||||
|
||||
@@ -167,13 +167,12 @@ class DiagnosticEmitter {
|
||||
// type conversion when needed.
|
||||
template <typename Arg>
|
||||
auto MakeAny(Arg arg) -> llvm::Any {
|
||||
if constexpr (Internal::DiagnosticTypeForArg<Arg>::Conversion ==
|
||||
DiagnosticTypeConversion::None) {
|
||||
return arg;
|
||||
} else {
|
||||
return converter_->ConvertArg(
|
||||
Internal::DiagnosticTypeForArg<Arg>::Conversion, arg);
|
||||
}
|
||||
llvm::Any converted = converter_->ConvertArg(arg);
|
||||
using Storage = Internal::DiagnosticTypeForArg<Arg>::StorageType;
|
||||
CARBON_CHECK(llvm::any_cast<Storage>(&converted))
|
||||
<< "Failed to convert argument of type " << typeid(Arg).name()
|
||||
<< " to its storage type " << typeid(Storage).name();
|
||||
return converted;
|
||||
}
|
||||
|
||||
template <typename LocT, typename AnnotateFn>
|
||||
|
||||
@@ -289,8 +289,7 @@ constexpr BoolValue BoolValue::True = BoolValue(1);
|
||||
// `self`, `Self`, or `base`.
|
||||
struct NameId : public IdBase, public Printable<NameId> {
|
||||
// names().GetFormatted() is used for diagnostics.
|
||||
using DiagnosticType =
|
||||
DiagnosticTypeInfo<std::string, DiagnosticTypeConversion::NameId>;
|
||||
using DiagnosticType = DiagnosticTypeInfo<std::string>;
|
||||
|
||||
// An explicitly invalid ID.
|
||||
static const NameId Invalid;
|
||||
@@ -427,8 +426,7 @@ constexpr InstBlockId InstBlockId::GlobalInit = InstBlockId(2);
|
||||
struct TypeId : public IdBase, public Printable<TypeId> {
|
||||
using ValueType = TypeInfo;
|
||||
// StringifyType() is used for diagnostics.
|
||||
using DiagnosticType =
|
||||
DiagnosticTypeInfo<std::string, DiagnosticTypeConversion::TypeId>;
|
||||
using DiagnosticType = DiagnosticTypeInfo<std::string>;
|
||||
|
||||
// The builtin TypeType.
|
||||
static const TypeId TypeType;
|
||||
|
||||
Reference in New Issue
Block a user