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:
Richard Smith
2024-03-27 18:01:28 +00:00
committed by GitHub
parent ebbc648342
commit d52ea8390a
4 changed files with 24 additions and 53 deletions
+7 -13
View File
@@ -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:
+9 -29
View File
@@ -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>
+6 -7
View File
@@ -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>
+2 -4
View File
@@ -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;