]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: TyTy: TyTy improved subclass casting and checking
authorJakub Dupak <dev@jakubdupak.com>
Tue, 3 Oct 2023 14:14:39 +0000 (16:14 +0200)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 18:09:12 +0000 (19:09 +0100)
Associate each subclass with its kind and create cast/match+cast
methods.

gcc/rust/ChangeLog:

* typecheck/rust-tyty.cc (InferType::InferType): Use static constant for kind information.
(ErrorType::ErrorType): Use static constant for kind information.
(TupleType::TupleType): Use static constant for kind information.
(BoolType::BoolType): Use static constant for kind information.
(IntType::IntType): Use static constant for kind information.
(UintType::UintType): Use static constant for kind information.
(FloatType::FloatType): Use static constant for kind information.
(USizeType::USizeType): Use static constant for kind information.
(ISizeType::ISizeType): Use static constant for kind information.
(CharType::CharType): Use static constant for kind information.
(ReferenceType::ReferenceType): Use static constant for kind information.
(PointerType::PointerType): Use static constant for kind information.
(ParamType::ParamType): Use static constant for kind information.
(StrType::StrType): Use static constant for kind information.
(NeverType::NeverType): Use static constant for kind information.
(PlaceholderType::PlaceholderType): Use static constant for kind information.
* typecheck/rust-tyty.h: Add static kind information to all TyTy classes.
Create safe cast and check methods.

Signed-off-by: Jakub Dupak <dev@jakubdupak.com>
gcc/rust/typecheck/rust-tyty.cc
gcc/rust/typecheck/rust-tyty.h

index 0a3ba85fff798cca3e2dd22b20c379cfbf14d206..772ca4866f020cddbc6d871be770a3b9ff7e051c 100644 (file)
@@ -962,14 +962,14 @@ BaseType::needs_generic_substitutions () const
 
 InferType::InferType (HirId ref, InferTypeKind infer_kind, TypeHint hint,
                      location_t locus, std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::INFER,
-             {Resolver::CanonicalPath::create_empty (), locus}, refs),
+  : BaseType (ref, ref, KIND, {Resolver::CanonicalPath::create_empty (), locus},
+             refs),
     infer_kind (infer_kind), default_hint (hint)
 {}
 
 InferType::InferType (HirId ref, HirId ty_ref, InferTypeKind infer_kind,
                      TypeHint hint, location_t locus, std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::INFER,
+  : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::create_empty (), locus}, refs),
     infer_kind (infer_kind), default_hint (hint)
 {}
@@ -1274,12 +1274,12 @@ InferType::apply_primitive_type_hint (const BaseType &hint)
 // ErrorType
 
 ErrorType::ErrorType (HirId ref, std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::ERROR,
+  : BaseType (ref, ref, KIND,
              {Resolver::CanonicalPath::create_empty (), UNDEF_LOCATION}, refs)
 {}
 
 ErrorType::ErrorType (HirId ref, HirId ty_ref, std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::ERROR,
+  : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::create_empty (), UNDEF_LOCATION}, refs)
 {}
 
@@ -1814,14 +1814,14 @@ ADTType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
 
 TupleType::TupleType (HirId ref, location_t locus, std::vector<TyVar> fields,
                      std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::TUPLE,
-             {Resolver::CanonicalPath::create_empty (), locus}, refs),
+  : BaseType (ref, ref, KIND, {Resolver::CanonicalPath::create_empty (), locus},
+             refs),
     fields (fields)
 {}
 
 TupleType::TupleType (HirId ref, HirId ty_ref, location_t locus,
                      std::vector<TyVar> fields, std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::TUPLE,
+  : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::create_empty (), locus}, refs),
     fields (fields)
 {}
@@ -2487,13 +2487,13 @@ SliceType::handle_substitions (SubstitutionArgumentMappings &mappings)
 // BoolType
 
 BoolType::BoolType (HirId ref, std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::BOOL,
+  : BaseType (ref, ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs)
 {}
 
 BoolType::BoolType (HirId ref, HirId ty_ref, std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::BOOL,
+  : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs)
 {}
@@ -2538,14 +2538,14 @@ BoolType::clone () const
 // IntType
 
 IntType::IntType (HirId ref, IntKind kind, std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::INT,
+  : BaseType (ref, ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs),
     int_kind (kind)
 {}
 
 IntType::IntType (HirId ref, HirId ty_ref, IntKind kind, std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::INT,
+  : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs),
     int_kind (kind)
@@ -2622,7 +2622,7 @@ IntType::is_equal (const BaseType &other) const
 // UintType
 
 UintType::UintType (HirId ref, UintKind kind, std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::UINT,
+  : BaseType (ref, ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs),
     uint_kind (kind)
@@ -2630,7 +2630,7 @@ UintType::UintType (HirId ref, UintKind kind, std::set<HirId> refs)
 
 UintType::UintType (HirId ref, HirId ty_ref, UintKind kind,
                    std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::UINT,
+  : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs),
     uint_kind (kind)
@@ -2707,7 +2707,7 @@ UintType::is_equal (const BaseType &other) const
 // FloatType
 
 FloatType::FloatType (HirId ref, FloatKind kind, std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::FLOAT,
+  : BaseType (ref, ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs),
     float_kind (kind)
@@ -2715,7 +2715,7 @@ FloatType::FloatType (HirId ref, FloatKind kind, std::set<HirId> refs)
 
 FloatType::FloatType (HirId ref, HirId ty_ref, FloatKind kind,
                      std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::FLOAT,
+  : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs),
     float_kind (kind)
@@ -2786,13 +2786,13 @@ FloatType::is_equal (const BaseType &other) const
 // UsizeType
 
 USizeType::USizeType (HirId ref, std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::USIZE,
+  : BaseType (ref, ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs)
 {}
 
 USizeType::USizeType (HirId ref, HirId ty_ref, std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::USIZE,
+  : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs)
 {}
@@ -2837,13 +2837,13 @@ USizeType::clone () const
 // ISizeType
 
 ISizeType::ISizeType (HirId ref, std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::ISIZE,
+  : BaseType (ref, ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs)
 {}
 
 ISizeType::ISizeType (HirId ref, HirId ty_ref, std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::ISIZE,
+  : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs)
 {}
@@ -2888,13 +2888,13 @@ ISizeType::clone () const
 // Char Type
 
 CharType::CharType (HirId ref, std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::CHAR,
+  : BaseType (ref, ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs)
 {}
 
 CharType::CharType (HirId ref, HirId ty_ref, std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::CHAR,
+  : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs)
 {}
@@ -2940,7 +2940,7 @@ CharType::clone () const
 
 ReferenceType::ReferenceType (HirId ref, TyVar base, Mutability mut,
                              std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::REF,
+  : BaseType (ref, ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs),
     base (base), mut (mut)
@@ -2948,7 +2948,7 @@ ReferenceType::ReferenceType (HirId ref, TyVar base, Mutability mut,
 
 ReferenceType::ReferenceType (HirId ref, HirId ty_ref, TyVar base,
                              Mutability mut, std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::REF,
+  : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs),
     base (base), mut (mut)
@@ -3096,7 +3096,7 @@ ReferenceType::handle_substitions (SubstitutionArgumentMappings &mappings)
 
 PointerType::PointerType (HirId ref, TyVar base, Mutability mut,
                          std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::POINTER,
+  : BaseType (ref, ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs),
     base (base), mut (mut)
@@ -3104,7 +3104,7 @@ PointerType::PointerType (HirId ref, TyVar base, Mutability mut,
 
 PointerType::PointerType (HirId ref, HirId ty_ref, TyVar base, Mutability mut,
                          std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::POINTER,
+  : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs),
     base (base), mut (mut)
@@ -3260,7 +3260,7 @@ ParamType::ParamType (std::string symbol, location_t locus, HirId ref,
                      HIR::GenericParam &param,
                      std::vector<TypeBoundPredicate> specified_bounds,
                      std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::PARAM,
+  : BaseType (ref, ref, KIND,
              {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
               locus},
              specified_bounds, refs),
@@ -3271,7 +3271,7 @@ ParamType::ParamType (bool is_trait_self, std::string symbol, location_t locus,
                      HirId ref, HirId ty_ref, HIR::GenericParam &param,
                      std::vector<TypeBoundPredicate> specified_bounds,
                      std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::PARAM,
+  : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
               locus},
              specified_bounds, refs),
@@ -3434,13 +3434,13 @@ ParamType::is_implicit_self_trait () const
 // StrType
 
 StrType::StrType (HirId ref, std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::STR,
+  : BaseType (ref, ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs)
 {}
 
 StrType::StrType (HirId ref, HirId ty_ref, std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::STR,
+  : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs)
 {}
@@ -3491,13 +3491,13 @@ StrType::is_equal (const BaseType &other) const
 // Never Type
 
 NeverType::NeverType (HirId ref, std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::NEVER,
+  : BaseType (ref, ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs)
 {}
 
 NeverType::NeverType (HirId ref, HirId ty_ref, std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::NEVER,
+  : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs)
 {}
@@ -3543,7 +3543,7 @@ NeverType::clone () const
 
 PlaceholderType::PlaceholderType (std::string symbol, HirId ref,
                                  std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::PLACEHOLDER,
+  : BaseType (ref, ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs),
     symbol (symbol)
@@ -3551,7 +3551,7 @@ PlaceholderType::PlaceholderType (std::string symbol, HirId ref,
 
 PlaceholderType::PlaceholderType (std::string symbol, HirId ref, HirId ty_ref,
                                  std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::PLACEHOLDER,
+  : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs),
     symbol (symbol)
@@ -3656,7 +3656,7 @@ ProjectionType::ProjectionType (
   HirId ref, BaseType *base, const Resolver::TraitReference *trait, DefId item,
   std::vector<SubstitutionParamMapping> subst_refs,
   SubstitutionArgumentMappings generic_arguments, std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::PROJECTION,
+  : BaseType (ref, ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs),
     SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
@@ -3668,7 +3668,7 @@ ProjectionType::ProjectionType (
   const Resolver::TraitReference *trait, DefId item,
   std::vector<SubstitutionParamMapping> subst_refs,
   SubstitutionArgumentMappings generic_arguments, std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::PROJECTION,
+  : BaseType (ref, ty_ref, KIND,
              {Resolver::CanonicalPath::create_empty (), BUILTINS_LOCATION},
              refs),
     SubstitutionRef (std::move (subst_refs), std::move (generic_arguments)),
@@ -3802,13 +3802,13 @@ ProjectionType::handle_substitions (
 DynamicObjectType::DynamicObjectType (
   HirId ref, RustIdent ident, std::vector<TypeBoundPredicate> specified_bounds,
   std::set<HirId> refs)
-  : BaseType (ref, ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
+  : BaseType (ref, ref, KIND, ident, specified_bounds, refs)
 {}
 
 DynamicObjectType::DynamicObjectType (
   HirId ref, HirId ty_ref, RustIdent ident,
   std::vector<TypeBoundPredicate> specified_bounds, std::set<HirId> refs)
-  : BaseType (ref, ty_ref, TypeKind::DYNAMIC, ident, specified_bounds, refs)
+  : BaseType (ref, ty_ref, KIND, ident, specified_bounds, refs)
 {}
 
 void
index 3ba24de10d9c380364d898bd32ab05d11ef519e0..0858502c6cb79ff8ced8dc06c9c7055366144183 100644 (file)
@@ -31,7 +31,9 @@ namespace Rust {
 
 namespace Resolver {
 class TraitReference;
+
 class TraitItemReference;
+
 class AssociatedImplTrait;
 } // namespace Resolver
 
@@ -116,9 +118,12 @@ public:
 
   bool satisfies_bound (const TypeBoundPredicate &predicate,
                        bool emit_error) const;
+
   bool bounds_compatible (const BaseType &other, location_t locus,
                          bool emit_error) const;
+
   void inherit_bounds (const BaseType &other);
+
   void inherit_bounds (
     const std::vector<TyTy::TypeBoundPredicate> &specified_bounds);
 
@@ -138,10 +143,13 @@ public:
 
   // get_combined_refs returns the chain of node refs involved in unification
   std::set<HirId> get_combined_refs () const;
+
   void append_reference (HirId id);
 
   std::string mappings_str () const;
+
   std::string debug_str () const;
+
   void debug () const;
 
   // FIXME this will eventually go away
@@ -168,6 +176,55 @@ public:
    * releasing the memory of the returned ty. */
   virtual BaseType *clone () const = 0;
 
+  // Check if TyTy::BaseType is of a specific type.
+  template <typename T>[[nodiscard]] bool is () const
+  {
+    static_assert (std::is_base_of<BaseType, T>::value,
+                  "Can only safely cast to TyTy types.");
+    return this->get_kind () == T::KIND;
+  }
+
+  template <typename T> T *as () const
+  {
+    static_assert (std::is_base_of<BaseType, T>::value,
+                  "Can only safely cast to TyTy types.");
+    rust_assert (this->is<T> ());
+    return static_cast<T *> (this);
+  }
+
+  template <typename T> T *as ()
+  {
+    static_assert (std::is_base_of<BaseType, T>::value,
+                  "Can only safely cast to TyTy types.");
+    rust_assert (this->is<T> ());
+    return static_cast<T *> (this);
+  }
+
+  // Check if TyTy::BaseType is of a specific type and convert it to that type
+  // if so.
+  // Returns nullptr otherwise. Works as a dynamic_cast, but without compiler
+  // RTTI.
+  template <typename T> T *try_as () const
+  {
+    static_assert (std::is_base_of<BaseType, T>::value,
+                  "Can only safely cast to TyTy types.");
+    if (!this->is<T> ())
+      return nullptr;
+
+    return static_cast<T *> (this);
+  }
+
+  // See above.
+  template <typename T> T *try_as ()
+  {
+    static_assert (std::is_base_of<BaseType, T>::value,
+                  "Can only safely cast to TyTy types.");
+    if (!this->is<T> ())
+      return nullptr;
+
+    return static_cast<T *> (this);
+  }
+
 protected:
   BaseType (HirId ref, HirId ty_ref, TypeKind kind, RustIdent ident,
            std::set<HirId> refs = std::set<HirId> ());
@@ -188,6 +245,8 @@ protected:
 class InferType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::INFER;
+
   enum InferTypeKind
   {
     GENERAL,
@@ -231,6 +290,7 @@ public:
             location_t locus, std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
+
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
@@ -255,6 +315,8 @@ private:
 class ErrorType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::ERROR;
+
   ErrorType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
 
   ErrorType (HirId ref, HirId ty_ref,
@@ -275,6 +337,8 @@ public:
 class ParamType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::PARAM;
+
   ParamType (std::string symbol, location_t locus, HirId ref,
             HIR::GenericParam &param,
             std::vector<TypeBoundPredicate> specified_bounds,
@@ -348,6 +412,8 @@ private:
 class TupleType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::TUPLE;
+
   TupleType (HirId ref, location_t locus,
             std::vector<TyVar> fields = std::vector<TyVar> (),
             std::set<HirId> refs = std::set<HirId> ());
@@ -511,7 +577,9 @@ public:
   std::string as_string () const;
 
   bool is_equal (const VariantDef &other) const;
+
   VariantDef *clone () const;
+
   VariantDef *monomorphized_clone () const;
 
   const RustIdent &get_ident () const;
@@ -530,6 +598,8 @@ private:
 class ADTType : public BaseType, public SubstitutionRef
 {
 public:
+  static constexpr auto KIND = TypeKind::ADT;
+
   enum ADTKind
   {
     STRUCT_STRUCT,
@@ -587,14 +657,19 @@ public:
   {}
 
   ADTKind get_adt_kind () const { return adt_kind; }
+
   ReprOptions get_repr_options () const { return repr; }
 
   bool is_struct_struct () const { return adt_kind == STRUCT_STRUCT; }
+
   bool is_tuple_struct () const { return adt_kind == TUPLE_STRUCT; }
+
   bool is_union () const { return adt_kind == UNION; }
+
   bool is_enum () const { return adt_kind == ENUM; }
 
   void accept_vis (TyVisitor &vis) override;
+
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
@@ -615,6 +690,7 @@ public:
   size_t number_of_variants () const { return variants.size (); }
 
   std::vector<VariantDef *> &get_variants () { return variants; }
+
   const std::vector<VariantDef *> &get_variants () const { return variants; }
 
   bool lookup_variant (const std::string &lookup,
@@ -663,6 +739,8 @@ private:
 class FnType : public BaseType, public SubstitutionRef
 {
 public:
+  static constexpr auto KIND = TypeKind::FNDEF;
+
   static const uint8_t FNTYPE_DEFAULT_FLAGS = 0x00;
   static const uint8_t FNTYPE_IS_METHOD_FLAG = 0x01;
   static const uint8_t FNTYPE_IS_EXTERN_FLAG = 0x02;
@@ -776,6 +854,8 @@ private:
 class FnPtr : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::FNPTR;
+
   FnPtr (HirId ref, location_t locus, std::vector<TyVar> params,
         TyVar result_type, std::set<HirId> refs = std::set<HirId> ())
     : BaseType (ref, ref, TypeKind::FNPTR,
@@ -821,6 +901,8 @@ private:
 class ClosureType : public BaseType, public SubstitutionRef
 {
 public:
+  static constexpr auto KIND = TypeKind::CLOSURE;
+
   ClosureType (HirId ref, DefId id, RustIdent ident,
               TyTy::TupleType *parameters, TyVar result_type,
               std::vector<SubstitutionParamMapping> subst_refs,
@@ -891,6 +973,8 @@ private:
 class ArrayType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::ARRAY;
+
   ArrayType (HirId ref, location_t locus, HIR::Expr &capacity_expr, TyVar base,
             std::set<HirId> refs = std::set<HirId> ())
     : BaseType (ref, ref, TypeKind::ARRAY,
@@ -934,6 +1018,8 @@ private:
 class SliceType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::SLICE;
+
   SliceType (HirId ref, location_t locus, TyVar base,
             std::set<HirId> refs = std::set<HirId> ())
     : BaseType (ref, ref, TypeKind::SLICE,
@@ -973,6 +1059,8 @@ private:
 class BoolType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::BOOL;
+
   BoolType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
   BoolType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ());
 
@@ -1000,6 +1088,8 @@ public:
     I128
   };
 
+  static constexpr auto KIND = TypeKind::INT;
+
   IntType (HirId ref, IntKind kind, std::set<HirId> refs = std::set<HirId> ());
   IntType (HirId ref, HirId ty_ref, IntKind kind,
           std::set<HirId> refs = std::set<HirId> ());
@@ -1026,6 +1116,8 @@ private:
 class UintType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::UINT;
+
   enum UintKind
   {
     U8,
@@ -1062,6 +1154,8 @@ private:
 class FloatType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::FLOAT;
+
   enum FloatKind
   {
     F32,
@@ -1094,6 +1188,8 @@ private:
 class USizeType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::USIZE;
+
   USizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
   USizeType (HirId ref, HirId ty_ref,
             std::set<HirId> refs = std::set<HirId> ());
@@ -1112,6 +1208,8 @@ public:
 class ISizeType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::ISIZE;
+
   ISizeType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
   ISizeType (HirId ref, HirId ty_ref,
             std::set<HirId> refs = std::set<HirId> ());
@@ -1130,6 +1228,8 @@ public:
 class CharType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::CHAR;
+
   CharType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
   CharType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ());
 
@@ -1147,6 +1247,8 @@ public:
 class StrType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::STR;
+
   StrType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
   StrType (HirId ref, HirId ty_ref, std::set<HirId> refs = std::set<HirId> ());
 
@@ -1167,6 +1269,8 @@ public:
 class DynamicObjectType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::DYNAMIC;
+
   DynamicObjectType (HirId ref, RustIdent ident,
                     std::vector<TypeBoundPredicate> specified_bounds,
                     std::set<HirId> refs = std::set<HirId> ());
@@ -1197,6 +1301,8 @@ public:
 class ReferenceType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::REF;
+
   ReferenceType (HirId ref, TyVar base, Mutability mut,
                 std::set<HirId> refs = std::set<HirId> ());
   ReferenceType (HirId ref, HirId ty_ref, TyVar base, Mutability mut,
@@ -1236,6 +1342,8 @@ private:
 class PointerType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::POINTER;
+
   PointerType (HirId ref, TyVar base, Mutability mut,
               std::set<HirId> refs = std::set<HirId> ());
   PointerType (HirId ref, HirId ty_ref, TyVar base, Mutability mut,
@@ -1284,11 +1392,15 @@ private:
 class NeverType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::NEVER;
+
   NeverType (HirId ref, std::set<HirId> refs = std::set<HirId> ());
+
   NeverType (HirId ref, HirId ty_ref,
             std::set<HirId> refs = std::set<HirId> ());
 
   void accept_vis (TyVisitor &vis) override;
+
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
@@ -1305,6 +1417,8 @@ public:
 class PlaceholderType : public BaseType
 {
 public:
+  static constexpr auto KIND = TypeKind::PLACEHOLDER;
+
   PlaceholderType (std::string symbol, HirId ref,
                   std::set<HirId> refs = std::set<HirId> ());
   PlaceholderType (std::string symbol, HirId ref, HirId ty_ref,
@@ -1340,6 +1454,8 @@ private:
 class ProjectionType : public BaseType, public SubstitutionRef
 {
 public:
+  static constexpr auto KIND = TypeKind::PROJECTION;
+
   ProjectionType (HirId ref, BaseType *base,
                  const Resolver::TraitReference *trait, DefId item,
                  std::vector<SubstitutionParamMapping> subst_refs,