Derive all ast::types from Castable

The hand-rolled `AsBlah()`, `IsBlah()` methods will be migrated in future changes.

Change-Id: I46a350a560f9eda8ca15f8ba8c95b17b9b6010b7
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/34261
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/ast/type/access_control_type.cc b/src/ast/type/access_control_type.cc
index 7bce6fe..8b33991 100644
--- a/src/ast/type/access_control_type.cc
+++ b/src/ast/type/access_control_type.cc
@@ -26,6 +26,8 @@
   assert(!subtype_->IsAccessControl());
 }
 
+AccessControlType::AccessControlType(AccessControlType&&) = default;
+
 AccessControlType::~AccessControlType() = default;
 
 bool AccessControlType::IsAccessControl() const {
diff --git a/src/ast/type/access_control_type.h b/src/ast/type/access_control_type.h
index 35a2f96..4b5071d 100644
--- a/src/ast/type/access_control_type.h
+++ b/src/ast/type/access_control_type.h
@@ -25,14 +25,14 @@
 namespace type {
 
 /// An access control type. Holds an access setting and pointer to another type.
-class AccessControlType : public Type {
+class AccessControlType : public Castable<AccessControlType, Type> {
  public:
   /// Constructor
   /// @param access the access control setting
   /// @param subtype the access controlled type
   AccessControlType(AccessControl access, Type* subtype);
   /// Move constructor
-  AccessControlType(AccessControlType&&) = default;
+  AccessControlType(AccessControlType&&);
   ~AccessControlType() override;
 
   /// @returns true if the type is an access control type
diff --git a/src/ast/type/alias_type.cc b/src/ast/type/alias_type.cc
index a4b6ac7..6944cf3 100644
--- a/src/ast/type/alias_type.cc
+++ b/src/ast/type/alias_type.cc
@@ -25,6 +25,8 @@
   assert(subtype_);
 }
 
+AliasType::AliasType(AliasType&&) = default;
+
 AliasType::~AliasType() = default;
 
 bool AliasType::IsAlias() const {
diff --git a/src/ast/type/alias_type.h b/src/ast/type/alias_type.h
index 38923ba..9e08d21 100644
--- a/src/ast/type/alias_type.h
+++ b/src/ast/type/alias_type.h
@@ -24,14 +24,14 @@
 namespace type {
 
 /// A type alias type. Holds a name and pointer to another type.
-class AliasType : public Type {
+class AliasType : public Castable<AliasType, Type> {
  public:
   /// Constructor
   /// @param name the alias name
   /// @param subtype the alias'd type
   AliasType(const std::string& name, Type* subtype);
   /// Move constructor
-  AliasType(AliasType&&) = default;
+  AliasType(AliasType&&);
   ~AliasType() override;
 
   /// @returns true if the type is an alias type
diff --git a/src/ast/type/array_type.h b/src/ast/type/array_type.h
index 042ae8c..8633f18 100644
--- a/src/ast/type/array_type.h
+++ b/src/ast/type/array_type.h
@@ -28,7 +28,7 @@
 namespace type {
 
 /// An array type. If size is zero then it is a runtime array.
-class ArrayType : public Type {
+class ArrayType : public Castable<ArrayType, Type> {
  public:
   /// Constructor for runtime array
   /// @param subtype the type of the array elements
diff --git a/src/ast/type/bool_type.cc b/src/ast/type/bool_type.cc
index e3c7971..e8f0af3 100644
--- a/src/ast/type/bool_type.cc
+++ b/src/ast/type/bool_type.cc
@@ -20,6 +20,8 @@
 
 BoolType::BoolType() = default;
 
+BoolType::BoolType(BoolType&&) = default;
+
 BoolType::~BoolType() = default;
 
 bool BoolType::IsBool() const {
diff --git a/src/ast/type/bool_type.h b/src/ast/type/bool_type.h
index 828e2c1..abd6e73 100644
--- a/src/ast/type/bool_type.h
+++ b/src/ast/type/bool_type.h
@@ -24,12 +24,12 @@
 namespace type {
 
 /// A boolean type
-class BoolType : public Type {
+class BoolType : public Castable<BoolType, Type> {
  public:
   /// Constructor
   BoolType();
   /// Move constructor
-  BoolType(BoolType&&) = default;
+  BoolType(BoolType&&);
   ~BoolType() override;
 
   /// @returns true if the type is a bool type
diff --git a/src/ast/type/depth_texture_type.cc b/src/ast/type/depth_texture_type.cc
index f3f79f6..79f8e06 100644
--- a/src/ast/type/depth_texture_type.cc
+++ b/src/ast/type/depth_texture_type.cc
@@ -33,7 +33,7 @@
 
 }  // namespace
 
-DepthTextureType::DepthTextureType(TextureDimension dim) : TextureType(dim) {
+DepthTextureType::DepthTextureType(TextureDimension dim) : Base(dim) {
   assert(IsValidDepthDimension(dim));
 }
 
diff --git a/src/ast/type/depth_texture_type.h b/src/ast/type/depth_texture_type.h
index 2d02ee6..ee05dc3 100644
--- a/src/ast/type/depth_texture_type.h
+++ b/src/ast/type/depth_texture_type.h
@@ -24,7 +24,7 @@
 namespace type {
 
 /// A depth texture type.
-class DepthTextureType : public TextureType {
+class DepthTextureType : public Castable<DepthTextureType, TextureType> {
  public:
   /// Constructor
   /// @param dim the dimensionality of the texture
diff --git a/src/ast/type/f32_type.cc b/src/ast/type/f32_type.cc
index df48732..ef9d5f1 100644
--- a/src/ast/type/f32_type.cc
+++ b/src/ast/type/f32_type.cc
@@ -20,6 +20,8 @@
 
 F32Type::F32Type() = default;
 
+F32Type::F32Type(F32Type&&) = default;
+
 F32Type::~F32Type() = default;
 
 bool F32Type::IsF32() const {
diff --git a/src/ast/type/f32_type.h b/src/ast/type/f32_type.h
index 0da82dd..bbc330d 100644
--- a/src/ast/type/f32_type.h
+++ b/src/ast/type/f32_type.h
@@ -24,12 +24,12 @@
 namespace type {
 
 /// A float 32 type
-class F32Type : public Type {
+class F32Type : public Castable<F32Type, Type> {
  public:
   /// Constructor
   F32Type();
   /// Move constructor
-  F32Type(F32Type&&) = default;
+  F32Type(F32Type&&);
   ~F32Type() override;
 
   /// @returns true if the type is an f32 type
diff --git a/src/ast/type/i32_type.cc b/src/ast/type/i32_type.cc
index 61b4990..04ad5aa 100644
--- a/src/ast/type/i32_type.cc
+++ b/src/ast/type/i32_type.cc
@@ -20,6 +20,8 @@
 
 I32Type::I32Type() = default;
 
+I32Type::I32Type(I32Type&&) = default;
+
 I32Type::~I32Type() = default;
 
 bool I32Type::IsI32() const {
diff --git a/src/ast/type/i32_type.h b/src/ast/type/i32_type.h
index a302cda..873e7b4 100644
--- a/src/ast/type/i32_type.h
+++ b/src/ast/type/i32_type.h
@@ -24,12 +24,12 @@
 namespace type {
 
 /// A signed int 32 type.
-class I32Type : public Type {
+class I32Type : public Castable<I32Type, Type> {
  public:
   /// Constructor
   I32Type();
   /// Move constructor
-  I32Type(I32Type&&) = default;
+  I32Type(I32Type&&);
   ~I32Type() override;
 
   /// @returns true if the type is an i32 type
diff --git a/src/ast/type/matrix_type.cc b/src/ast/type/matrix_type.cc
index 8f0f092..f6dfb8c 100644
--- a/src/ast/type/matrix_type.cc
+++ b/src/ast/type/matrix_type.cc
@@ -31,6 +31,8 @@
   assert(columns < 5);
 }
 
+MatrixType::MatrixType(MatrixType&&) = default;
+
 MatrixType::~MatrixType() = default;
 
 bool MatrixType::IsMatrix() const {
diff --git a/src/ast/type/matrix_type.h b/src/ast/type/matrix_type.h
index 458c1aa..ad62da4 100644
--- a/src/ast/type/matrix_type.h
+++ b/src/ast/type/matrix_type.h
@@ -24,7 +24,7 @@
 namespace type {
 
 /// A matrix type
-class MatrixType : public Type {
+class MatrixType : public Castable<MatrixType, Type> {
  public:
   /// Constructor
   /// @param subtype type matrix type
@@ -32,7 +32,7 @@
   /// @param columns the number of columns in the matrix
   MatrixType(Type* subtype, uint32_t rows, uint32_t columns);
   /// Move constructor
-  MatrixType(MatrixType&&) = default;
+  MatrixType(MatrixType&&);
   ~MatrixType() override;
 
   /// @returns true if the type is a matrix type
diff --git a/src/ast/type/multisampled_texture_type.cc b/src/ast/type/multisampled_texture_type.cc
index 7bfc885..7de7dc5 100644
--- a/src/ast/type/multisampled_texture_type.cc
+++ b/src/ast/type/multisampled_texture_type.cc
@@ -23,7 +23,7 @@
 
 MultisampledTextureType::MultisampledTextureType(TextureDimension dim,
                                                  Type* type)
-    : TextureType(dim), type_(type) {
+    : Base(dim), type_(type) {
   assert(type_);
 }
 
diff --git a/src/ast/type/multisampled_texture_type.h b/src/ast/type/multisampled_texture_type.h
index ae8f38e..4c68c56 100644
--- a/src/ast/type/multisampled_texture_type.h
+++ b/src/ast/type/multisampled_texture_type.h
@@ -24,7 +24,8 @@
 namespace type {
 
 /// A multisampled texture type.
-class MultisampledTextureType : public TextureType {
+class MultisampledTextureType
+    : public Castable<MultisampledTextureType, TextureType> {
  public:
   /// Constructor
   /// @param dim the dimensionality of the texture
diff --git a/src/ast/type/pointer_type.cc b/src/ast/type/pointer_type.cc
index e6083c8..b81382c 100644
--- a/src/ast/type/pointer_type.cc
+++ b/src/ast/type/pointer_type.cc
@@ -31,6 +31,8 @@
   return out.str();
 }
 
+PointerType::PointerType(PointerType&&) = default;
+
 PointerType::~PointerType() = default;
 
 }  // namespace type
diff --git a/src/ast/type/pointer_type.h b/src/ast/type/pointer_type.h
index fa97975..f27eab6 100644
--- a/src/ast/type/pointer_type.h
+++ b/src/ast/type/pointer_type.h
@@ -26,14 +26,14 @@
 namespace type {
 
 /// A pointer type.
-class PointerType : public Type {
+class PointerType : public Castable<PointerType, Type> {
  public:
   /// Construtor
   /// @param subtype the pointee type
   /// @param storage_class the storage class of the pointer
   explicit PointerType(Type* subtype, StorageClass storage_class);
   /// Move constructor
-  PointerType(PointerType&&) = default;
+  PointerType(PointerType&&);
   ~PointerType() override;
 
   /// @returns true if the type is a pointer type
diff --git a/src/ast/type/sampled_texture_type.cc b/src/ast/type/sampled_texture_type.cc
index 0ef5578..78576b7 100644
--- a/src/ast/type/sampled_texture_type.cc
+++ b/src/ast/type/sampled_texture_type.cc
@@ -22,7 +22,7 @@
 namespace type {
 
 SampledTextureType::SampledTextureType(TextureDimension dim, Type* type)
-    : TextureType(dim), type_(type) {
+    : Base(dim), type_(type) {
   assert(type_);
 }
 
diff --git a/src/ast/type/sampled_texture_type.h b/src/ast/type/sampled_texture_type.h
index e387b87..3b1fb3f 100644
--- a/src/ast/type/sampled_texture_type.h
+++ b/src/ast/type/sampled_texture_type.h
@@ -24,7 +24,7 @@
 namespace type {
 
 /// A sampled texture type.
-class SampledTextureType : public TextureType {
+class SampledTextureType : public Castable<SampledTextureType, TextureType> {
  public:
   /// Constructor
   /// @param dim the dimensionality of the texture
diff --git a/src/ast/type/sampler_type.h b/src/ast/type/sampler_type.h
index 74e0443..d064a88 100644
--- a/src/ast/type/sampler_type.h
+++ b/src/ast/type/sampler_type.h
@@ -34,7 +34,7 @@
 std::ostream& operator<<(std::ostream& out, SamplerKind kind);
 
 /// A sampler type.
-class SamplerType : public Type {
+class SamplerType : public Castable<SamplerType, Type> {
  public:
   /// Constructor
   /// @param kind the kind of sampler
diff --git a/src/ast/type/storage_texture_type.cc b/src/ast/type/storage_texture_type.cc
index e4f2769..d544963 100644
--- a/src/ast/type/storage_texture_type.cc
+++ b/src/ast/type/storage_texture_type.cc
@@ -153,7 +153,7 @@
 StorageTextureType::StorageTextureType(TextureDimension dim,
                                        AccessControl access,
                                        ImageFormat format)
-    : TextureType(dim), access_(access), image_format_(format) {
+    : Base(dim), access_(access), image_format_(format) {
   assert(IsValidStorageDimension(dim));
 }
 
diff --git a/src/ast/type/storage_texture_type.h b/src/ast/type/storage_texture_type.h
index a8a878c..8157b07 100644
--- a/src/ast/type/storage_texture_type.h
+++ b/src/ast/type/storage_texture_type.h
@@ -66,7 +66,7 @@
 std::ostream& operator<<(std::ostream& out, ImageFormat dim);
 
 /// A storage texture type.
-class StorageTextureType : public TextureType {
+class StorageTextureType : public Castable<StorageTextureType, TextureType> {
  public:
   /// Constructor
   /// @param dim the dimensionality of the texture
diff --git a/src/ast/type/struct_type.h b/src/ast/type/struct_type.h
index 99ee491..3ab4487 100644
--- a/src/ast/type/struct_type.h
+++ b/src/ast/type/struct_type.h
@@ -26,7 +26,7 @@
 namespace type {
 
 /// A structure type
-class StructType : public Type {
+class StructType : public Castable<StructType, Type> {
  public:
   /// Constructor
   /// @param name the name of the struct
diff --git a/src/ast/type/texture_type.h b/src/ast/type/texture_type.h
index 14cac19..249c85c 100644
--- a/src/ast/type/texture_type.h
+++ b/src/ast/type/texture_type.h
@@ -51,7 +51,7 @@
 std::ostream& operator<<(std::ostream& out, TextureDimension dim);
 
 /// A texture type.
-class TextureType : public Type {
+class TextureType : public Castable<TextureType, Type> {
  public:
   /// Constructor
   /// @param dim the dimensionality of the texture
diff --git a/src/ast/type/type.cc b/src/ast/type/type.cc
index a0f29b7..51c48f0 100644
--- a/src/ast/type/type.cc
+++ b/src/ast/type/type.cc
@@ -37,6 +37,8 @@
 
 Type::Type() = default;
 
+Type::  Type(Type&&) = default;
+
 Type::~Type() = default;
 
 Type* Type::UnwrapPtrIfNeeded() {
diff --git a/src/ast/type/type.h b/src/ast/type/type.h
index 54903ff..17cd265 100644
--- a/src/ast/type/type.h
+++ b/src/ast/type/type.h
@@ -17,6 +17,8 @@
 
 #include <string>
 
+#include "src/castable.h"
+
 namespace tint {
 namespace ast {
 namespace type {
@@ -40,11 +42,11 @@
 enum class MemoryLayout { kUniformBuffer, kStorageBuffer };
 
 /// Base class for a type in the system
-class Type {
+class Type : public Castable<Type> {
  public:
   /// Move constructor
-  Type(Type&&) = default;
-  virtual ~Type();
+  Type(Type&&);
+  ~Type() override;
 
   /// @returns true if the type is an access control type
   virtual bool IsAccessControl() const;
diff --git a/src/ast/type/u32_type.h b/src/ast/type/u32_type.h
index 64bc641..53ba6e3 100644
--- a/src/ast/type/u32_type.h
+++ b/src/ast/type/u32_type.h
@@ -24,7 +24,7 @@
 namespace type {
 
 /// A unsigned int 32 type.
-class U32Type : public Type {
+class U32Type : public Castable<U32Type, Type> {
  public:
   /// Constructor
   U32Type();
diff --git a/src/ast/type/vector_type.h b/src/ast/type/vector_type.h
index 3d6313d..257d27c 100644
--- a/src/ast/type/vector_type.h
+++ b/src/ast/type/vector_type.h
@@ -24,7 +24,7 @@
 namespace type {
 
 /// A vector type.
-class VectorType : public Type {
+class VectorType : public Castable<VectorType, Type> {
  public:
   /// Constructor
   /// @param subtype the vector element type
diff --git a/src/ast/type/void_type.h b/src/ast/type/void_type.h
index 2a02f46..4aa4842 100644
--- a/src/ast/type/void_type.h
+++ b/src/ast/type/void_type.h
@@ -24,7 +24,7 @@
 namespace type {
 
 /// A void type
-class VoidType : public Type {
+class VoidType : public Castable<VoidType, Type> {
  public:
   /// Constructor
   VoidType();