Replace Type::(Is|As)Matrix with Castable

Change-Id: I861aed231604a8bfba1f4cf3659b4863556fc3c4
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/34268
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/ast/type/access_control_type_test.cc b/src/ast/type/access_control_type_test.cc
index 24d908b..94e0e73 100644
--- a/src/ast/type/access_control_type_test.cc
+++ b/src/ast/type/access_control_type_test.cc
@@ -27,6 +27,7 @@
 #include "src/ast/type/bool_type.h"
 #include "src/ast/type/f32_type.h"
 #include "src/ast/type/i32_type.h"
+#include "src/ast/type/matrix_type.h"
 #include "src/ast/type/pointer_type.h"
 #include "src/ast/type/struct_type.h"
 #include "src/ast/type/u32_type.h"
@@ -56,7 +57,7 @@
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
   EXPECT_FALSE(ty->Is<I32Type>());
-  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->Is<MatrixType>());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
   EXPECT_FALSE(ty->IsStruct());
diff --git a/src/ast/type/alias_type_test.cc b/src/ast/type/alias_type_test.cc
index 7e76f80..99075a9 100644
--- a/src/ast/type/alias_type_test.cc
+++ b/src/ast/type/alias_type_test.cc
@@ -28,6 +28,7 @@
 #include "src/ast/type/bool_type.h"
 #include "src/ast/type/f32_type.h"
 #include "src/ast/type/i32_type.h"
+#include "src/ast/type/matrix_type.h"
 #include "src/ast/type/pointer_type.h"
 #include "src/ast/type/struct_type.h"
 #include "src/ast/type/u32_type.h"
@@ -57,7 +58,7 @@
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
   EXPECT_FALSE(ty->Is<I32Type>());
-  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->Is<MatrixType>());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
   EXPECT_FALSE(ty->IsStruct());
diff --git a/src/ast/type/array_type_test.cc b/src/ast/type/array_type_test.cc
index 5c9bbfa..5c0ac8f 100644
--- a/src/ast/type/array_type_test.cc
+++ b/src/ast/type/array_type_test.cc
@@ -23,6 +23,7 @@
 #include "src/ast/type/bool_type.h"
 #include "src/ast/type/f32_type.h"
 #include "src/ast/type/i32_type.h"
+#include "src/ast/type/matrix_type.h"
 #include "src/ast/type/u32_type.h"
 
 namespace tint {
@@ -61,7 +62,7 @@
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
   EXPECT_FALSE(ty->Is<I32Type>());
-  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->Is<MatrixType>());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
   EXPECT_FALSE(ty->IsStruct());
diff --git a/src/ast/type/bool_type_test.cc b/src/ast/type/bool_type_test.cc
index a04d882..05ee0bb 100644
--- a/src/ast/type/bool_type_test.cc
+++ b/src/ast/type/bool_type_test.cc
@@ -19,6 +19,7 @@
 #include "src/ast/type/array_type.h"
 #include "src/ast/type/f32_type.h"
 #include "src/ast/type/i32_type.h"
+#include "src/ast/type/matrix_type.h"
 
 namespace tint {
 namespace ast {
@@ -36,7 +37,7 @@
   EXPECT_TRUE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
   EXPECT_FALSE(ty->Is<I32Type>());
-  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->Is<MatrixType>());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
   EXPECT_FALSE(ty->IsStruct());
diff --git a/src/ast/type/depth_texture_type_test.cc b/src/ast/type/depth_texture_type_test.cc
index af8231a..1e467ab 100644
--- a/src/ast/type/depth_texture_type_test.cc
+++ b/src/ast/type/depth_texture_type_test.cc
@@ -21,6 +21,7 @@
 #include "src/ast/type/bool_type.h"
 #include "src/ast/type/f32_type.h"
 #include "src/ast/type/i32_type.h"
+#include "src/ast/type/matrix_type.h"
 
 namespace tint {
 namespace ast {
@@ -38,7 +39,7 @@
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
   EXPECT_FALSE(ty->Is<I32Type>());
-  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->Is<MatrixType>());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
   EXPECT_FALSE(ty->IsStruct());
diff --git a/src/ast/type/f32_type_test.cc b/src/ast/type/f32_type_test.cc
index 1cf54b3..75e7a53 100644
--- a/src/ast/type/f32_type_test.cc
+++ b/src/ast/type/f32_type_test.cc
@@ -19,6 +19,7 @@
 #include "src/ast/type/array_type.h"
 #include "src/ast/type/bool_type.h"
 #include "src/ast/type/i32_type.h"
+#include "src/ast/type/matrix_type.h"
 
 namespace tint {
 namespace ast {
@@ -36,7 +37,7 @@
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_TRUE(ty->Is<F32Type>());
   EXPECT_FALSE(ty->Is<I32Type>());
-  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->Is<MatrixType>());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
   EXPECT_FALSE(ty->IsStruct());
diff --git a/src/ast/type/i32_type_test.cc b/src/ast/type/i32_type_test.cc
index 340447a..11000af 100644
--- a/src/ast/type/i32_type_test.cc
+++ b/src/ast/type/i32_type_test.cc
@@ -19,6 +19,7 @@
 #include "src/ast/type/array_type.h"
 #include "src/ast/type/bool_type.h"
 #include "src/ast/type/f32_type.h"
+#include "src/ast/type/matrix_type.h"
 
 namespace tint {
 namespace ast {
@@ -36,7 +37,7 @@
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
   EXPECT_TRUE(ty->Is<I32Type>());
-  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->Is<MatrixType>());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
   EXPECT_FALSE(ty->IsStruct());
diff --git a/src/ast/type/matrix_type.cc b/src/ast/type/matrix_type.cc
index f6dfb8c..da2ef68 100644
--- a/src/ast/type/matrix_type.cc
+++ b/src/ast/type/matrix_type.cc
@@ -35,10 +35,6 @@
 
 MatrixType::~MatrixType() = default;
 
-bool MatrixType::IsMatrix() const {
-  return true;
-}
-
 std::string MatrixType::type_name() const {
   return "__mat_" + std::to_string(rows_) + "_" + std::to_string(columns_) +
          subtype_->type_name();
diff --git a/src/ast/type/matrix_type.h b/src/ast/type/matrix_type.h
index ad62da4..d08d09e 100644
--- a/src/ast/type/matrix_type.h
+++ b/src/ast/type/matrix_type.h
@@ -35,9 +35,6 @@
   MatrixType(MatrixType&&);
   ~MatrixType() override;
 
-  /// @returns true if the type is a matrix type
-  bool IsMatrix() const override;
-
   /// @returns the type of the matrix
   Type* type() const { return subtype_; }
   /// @returns the number of rows in the matrix
diff --git a/src/ast/type/matrix_type_test.cc b/src/ast/type/matrix_type_test.cc
index 42d02d0..96d7b70 100644
--- a/src/ast/type/matrix_type_test.cc
+++ b/src/ast/type/matrix_type_test.cc
@@ -46,7 +46,7 @@
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
   EXPECT_FALSE(ty->Is<I32Type>());
-  EXPECT_TRUE(ty->IsMatrix());
+  EXPECT_TRUE(ty->Is<MatrixType>());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
   EXPECT_FALSE(ty->IsStruct());
diff --git a/src/ast/type/multisampled_texture_type_test.cc b/src/ast/type/multisampled_texture_type_test.cc
index 0f52be4..1ba22da 100644
--- a/src/ast/type/multisampled_texture_type_test.cc
+++ b/src/ast/type/multisampled_texture_type_test.cc
@@ -20,6 +20,7 @@
 #include "src/ast/type/bool_type.h"
 #include "src/ast/type/f32_type.h"
 #include "src/ast/type/i32_type.h"
+#include "src/ast/type/matrix_type.h"
 
 namespace tint {
 namespace ast {
@@ -38,7 +39,7 @@
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
   EXPECT_FALSE(ty->Is<I32Type>());
-  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->Is<MatrixType>());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
   EXPECT_FALSE(ty->IsStruct());
diff --git a/src/ast/type/pointer_type_test.cc b/src/ast/type/pointer_type_test.cc
index 420a10b..51e4f4a 100644
--- a/src/ast/type/pointer_type_test.cc
+++ b/src/ast/type/pointer_type_test.cc
@@ -20,6 +20,7 @@
 #include "src/ast/type/bool_type.h"
 #include "src/ast/type/f32_type.h"
 #include "src/ast/type/i32_type.h"
+#include "src/ast/type/matrix_type.h"
 
 namespace tint {
 namespace ast {
@@ -45,7 +46,7 @@
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
   EXPECT_FALSE(ty->Is<I32Type>());
-  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->Is<MatrixType>());
   EXPECT_TRUE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
   EXPECT_FALSE(ty->IsStruct());
diff --git a/src/ast/type/sampled_texture_type_test.cc b/src/ast/type/sampled_texture_type_test.cc
index 6e1cbbd..5421005 100644
--- a/src/ast/type/sampled_texture_type_test.cc
+++ b/src/ast/type/sampled_texture_type_test.cc
@@ -20,6 +20,7 @@
 #include "src/ast/type/bool_type.h"
 #include "src/ast/type/f32_type.h"
 #include "src/ast/type/i32_type.h"
+#include "src/ast/type/matrix_type.h"
 
 namespace tint {
 namespace ast {
@@ -38,7 +39,7 @@
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
   EXPECT_FALSE(ty->Is<I32Type>());
-  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->Is<MatrixType>());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
   EXPECT_FALSE(ty->IsStruct());
diff --git a/src/ast/type/sampler_type_test.cc b/src/ast/type/sampler_type_test.cc
index 41dcfea..2c03f2d 100644
--- a/src/ast/type/sampler_type_test.cc
+++ b/src/ast/type/sampler_type_test.cc
@@ -20,6 +20,7 @@
 #include "src/ast/type/bool_type.h"
 #include "src/ast/type/f32_type.h"
 #include "src/ast/type/i32_type.h"
+#include "src/ast/type/matrix_type.h"
 
 namespace tint {
 namespace ast {
@@ -48,7 +49,7 @@
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
   EXPECT_FALSE(ty->Is<I32Type>());
-  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->Is<MatrixType>());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_TRUE(ty->IsSampler());
   EXPECT_FALSE(ty->IsStruct());
diff --git a/src/ast/type/storage_texture_type_test.cc b/src/ast/type/storage_texture_type_test.cc
index 780e316..03487de 100644
--- a/src/ast/type/storage_texture_type_test.cc
+++ b/src/ast/type/storage_texture_type_test.cc
@@ -23,6 +23,7 @@
 #include "src/ast/type/bool_type.h"
 #include "src/ast/type/f32_type.h"
 #include "src/ast/type/i32_type.h"
+#include "src/ast/type/matrix_type.h"
 #include "src/type_determiner.h"
 
 namespace tint {
@@ -42,7 +43,7 @@
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
   EXPECT_FALSE(ty->Is<I32Type>());
-  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->Is<MatrixType>());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
   EXPECT_FALSE(ty->IsStruct());
diff --git a/src/ast/type/struct_type_test.cc b/src/ast/type/struct_type_test.cc
index 8e382bd..a3dd3b2 100644
--- a/src/ast/type/struct_type_test.cc
+++ b/src/ast/type/struct_type_test.cc
@@ -26,6 +26,7 @@
 #include "src/ast/type/bool_type.h"
 #include "src/ast/type/f32_type.h"
 #include "src/ast/type/i32_type.h"
+#include "src/ast/type/matrix_type.h"
 #include "src/ast/type/u32_type.h"
 #include "src/ast/type/vector_type.h"
 
@@ -53,7 +54,7 @@
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
   EXPECT_FALSE(ty->Is<I32Type>());
-  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->Is<MatrixType>());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
   EXPECT_TRUE(ty->IsStruct());
diff --git a/src/ast/type/type.cc b/src/ast/type/type.cc
index c496356..51b8745 100644
--- a/src/ast/type/type.cc
+++ b/src/ast/type/type.cc
@@ -66,10 +66,6 @@
   return UnwrapIfNeeded()->UnwrapPtrIfNeeded()->UnwrapIfNeeded();
 }
 
-bool Type::IsMatrix() const {
-  return false;
-}
-
 bool Type::IsPointer() const {
   return false;
 }
@@ -115,7 +111,7 @@
 }
 
 bool Type::is_float_matrix() {
-  return IsMatrix() && AsMatrix()->type()->is_float_scalar();
+  return Is<MatrixType>() && As<MatrixType>()->type()->is_float_scalar();
 }
 
 bool Type::is_float_vector() {
@@ -150,11 +146,6 @@
   return is_unsigned_scalar_or_vector() || is_signed_scalar_or_vector();
 }
 
-const MatrixType* Type::AsMatrix() const {
-  assert(IsMatrix());
-  return static_cast<const MatrixType*>(this);
-}
-
 const PointerType* Type::AsPointer() const {
   assert(IsPointer());
   return static_cast<const PointerType*>(this);
@@ -190,11 +181,6 @@
   return static_cast<const VoidType*>(this);
 }
 
-MatrixType* Type::AsMatrix() {
-  assert(IsMatrix());
-  return static_cast<MatrixType*>(this);
-}
-
 PointerType* Type::AsPointer() {
   assert(IsPointer());
   return static_cast<PointerType*>(this);
diff --git a/src/ast/type/type.h b/src/ast/type/type.h
index 4fd931e..1c3efdc 100644
--- a/src/ast/type/type.h
+++ b/src/ast/type/type.h
@@ -23,7 +23,6 @@
 namespace ast {
 namespace type {
 
-class MatrixType;
 class PointerType;
 class SamplerType;
 class StructType;
@@ -42,8 +41,6 @@
   Type(Type&&);
   ~Type() override;
 
-  /// @returns true if the type is a matrix type
-  virtual bool IsMatrix() const;
   /// @returns true if the type is a ptr type
   virtual bool IsPointer() const;
   /// @returns true if the type is a sampler
@@ -113,8 +110,6 @@
   /// @returns true if this type is an integer scalar or vector
   bool is_integer_scalar_or_vector();
 
-  /// @returns the type as a matrix type
-  const MatrixType* AsMatrix() const;
   /// @returns the type as a pointer type
   const PointerType* AsPointer() const;
   /// @returns the type as a sampler type
@@ -130,8 +125,6 @@
   /// @returns the type as a void type
   const VoidType* AsVoid() const;
 
-  /// @returns the type as a matrix type
-  MatrixType* AsMatrix();
   /// @returns the type as a pointer type
   PointerType* AsPointer();
   /// @returns the type as a sampler type
diff --git a/src/ast/type/u32_type_test.cc b/src/ast/type/u32_type_test.cc
index 963d3bc..bc8f21a 100644
--- a/src/ast/type/u32_type_test.cc
+++ b/src/ast/type/u32_type_test.cc
@@ -20,6 +20,7 @@
 #include "src/ast/type/bool_type.h"
 #include "src/ast/type/f32_type.h"
 #include "src/ast/type/i32_type.h"
+#include "src/ast/type/matrix_type.h"
 
 namespace tint {
 namespace ast {
@@ -37,7 +38,7 @@
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
   EXPECT_FALSE(ty->Is<I32Type>());
-  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->Is<MatrixType>());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
   EXPECT_FALSE(ty->IsStruct());
diff --git a/src/ast/type/vector_type_test.cc b/src/ast/type/vector_type_test.cc
index 9c9d930..8872f7d 100644
--- a/src/ast/type/vector_type_test.cc
+++ b/src/ast/type/vector_type_test.cc
@@ -20,6 +20,7 @@
 #include "src/ast/type/bool_type.h"
 #include "src/ast/type/f32_type.h"
 #include "src/ast/type/i32_type.h"
+#include "src/ast/type/matrix_type.h"
 
 namespace tint {
 namespace ast {
@@ -45,7 +46,7 @@
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
   EXPECT_FALSE(ty->Is<I32Type>());
-  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->Is<MatrixType>());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
   EXPECT_FALSE(ty->IsStruct());
diff --git a/src/inspector/inspector.cc b/src/inspector/inspector.cc
index ae58e43..bf6c289 100644
--- a/src/inspector/inspector.cc
+++ b/src/inspector/inspector.cc
@@ -387,8 +387,8 @@
 
     if (base_type->Is<ast::type::ArrayType>()) {
       base_type = base_type->As<ast::type::ArrayType>()->type();
-    } else if (base_type->IsMatrix()) {
-      base_type = base_type->AsMatrix()->type();
+    } else if (base_type->Is<ast::type::MatrixType>()) {
+      base_type = base_type->As<ast::type::MatrixType>()->type();
     } else if (base_type->IsVector()) {
       base_type = base_type->AsVector()->type();
     }
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index 0ba75d1..809a38c 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -1359,8 +1359,8 @@
     return create<ast::TypeConstructorExpression>(type,
                                                   std::move(ast_components));
   }
-  if (type->IsMatrix()) {
-    const auto* mat_ty = type->AsMatrix();
+  if (type->Is<ast::type::MatrixType>()) {
+    const auto* mat_ty = type->As<ast::type::MatrixType>();
     // Matrix components are columns
     auto* column_ty = ast_module_.create<ast::type::VectorType>(mat_ty->type(),
                                                                 mat_ty->rows());
diff --git a/src/reader/spirv/parser_impl_convert_type_test.cc b/src/reader/spirv/parser_impl_convert_type_test.cc
index 4893bb1..787e4e7 100644
--- a/src/reader/spirv/parser_impl_convert_type_test.cc
+++ b/src/reader/spirv/parser_impl_convert_type_test.cc
@@ -276,58 +276,67 @@
   EXPECT_TRUE(p->BuildInternalModule());
 
   auto* m22 = p->ConvertType(22);
-  EXPECT_TRUE(m22->IsMatrix());
-  EXPECT_TRUE(m22->AsMatrix()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(m22->AsMatrix()->rows(), 2u);
-  EXPECT_EQ(m22->AsMatrix()->columns(), 2u);
+  EXPECT_TRUE(m22->Is<ast::type::MatrixType>());
+  EXPECT_TRUE(
+      m22->As<ast::type::MatrixType>()->type()->Is<ast::type::F32Type>());
+  EXPECT_EQ(m22->As<ast::type::MatrixType>()->rows(), 2u);
+  EXPECT_EQ(m22->As<ast::type::MatrixType>()->columns(), 2u);
 
   auto* m23 = p->ConvertType(23);
-  EXPECT_TRUE(m23->IsMatrix());
-  EXPECT_TRUE(m23->AsMatrix()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(m23->AsMatrix()->rows(), 2u);
-  EXPECT_EQ(m23->AsMatrix()->columns(), 3u);
+  EXPECT_TRUE(m23->Is<ast::type::MatrixType>());
+  EXPECT_TRUE(
+      m23->As<ast::type::MatrixType>()->type()->Is<ast::type::F32Type>());
+  EXPECT_EQ(m23->As<ast::type::MatrixType>()->rows(), 2u);
+  EXPECT_EQ(m23->As<ast::type::MatrixType>()->columns(), 3u);
 
   auto* m24 = p->ConvertType(24);
-  EXPECT_TRUE(m24->IsMatrix());
-  EXPECT_TRUE(m24->AsMatrix()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(m24->AsMatrix()->rows(), 2u);
-  EXPECT_EQ(m24->AsMatrix()->columns(), 4u);
+  EXPECT_TRUE(m24->Is<ast::type::MatrixType>());
+  EXPECT_TRUE(
+      m24->As<ast::type::MatrixType>()->type()->Is<ast::type::F32Type>());
+  EXPECT_EQ(m24->As<ast::type::MatrixType>()->rows(), 2u);
+  EXPECT_EQ(m24->As<ast::type::MatrixType>()->columns(), 4u);
 
   auto* m32 = p->ConvertType(32);
-  EXPECT_TRUE(m32->IsMatrix());
-  EXPECT_TRUE(m32->AsMatrix()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(m32->AsMatrix()->rows(), 3u);
-  EXPECT_EQ(m32->AsMatrix()->columns(), 2u);
+  EXPECT_TRUE(m32->Is<ast::type::MatrixType>());
+  EXPECT_TRUE(
+      m32->As<ast::type::MatrixType>()->type()->Is<ast::type::F32Type>());
+  EXPECT_EQ(m32->As<ast::type::MatrixType>()->rows(), 3u);
+  EXPECT_EQ(m32->As<ast::type::MatrixType>()->columns(), 2u);
 
   auto* m33 = p->ConvertType(33);
-  EXPECT_TRUE(m33->IsMatrix());
-  EXPECT_TRUE(m33->AsMatrix()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(m33->AsMatrix()->rows(), 3u);
-  EXPECT_EQ(m33->AsMatrix()->columns(), 3u);
+  EXPECT_TRUE(m33->Is<ast::type::MatrixType>());
+  EXPECT_TRUE(
+      m33->As<ast::type::MatrixType>()->type()->Is<ast::type::F32Type>());
+  EXPECT_EQ(m33->As<ast::type::MatrixType>()->rows(), 3u);
+  EXPECT_EQ(m33->As<ast::type::MatrixType>()->columns(), 3u);
 
   auto* m34 = p->ConvertType(34);
-  EXPECT_TRUE(m34->IsMatrix());
-  EXPECT_TRUE(m34->AsMatrix()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(m34->AsMatrix()->rows(), 3u);
-  EXPECT_EQ(m34->AsMatrix()->columns(), 4u);
+  EXPECT_TRUE(m34->Is<ast::type::MatrixType>());
+  EXPECT_TRUE(
+      m34->As<ast::type::MatrixType>()->type()->Is<ast::type::F32Type>());
+  EXPECT_EQ(m34->As<ast::type::MatrixType>()->rows(), 3u);
+  EXPECT_EQ(m34->As<ast::type::MatrixType>()->columns(), 4u);
 
   auto* m42 = p->ConvertType(42);
-  EXPECT_TRUE(m42->IsMatrix());
-  EXPECT_TRUE(m42->AsMatrix()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(m42->AsMatrix()->rows(), 4u);
-  EXPECT_EQ(m42->AsMatrix()->columns(), 2u);
+  EXPECT_TRUE(m42->Is<ast::type::MatrixType>());
+  EXPECT_TRUE(
+      m42->As<ast::type::MatrixType>()->type()->Is<ast::type::F32Type>());
+  EXPECT_EQ(m42->As<ast::type::MatrixType>()->rows(), 4u);
+  EXPECT_EQ(m42->As<ast::type::MatrixType>()->columns(), 2u);
 
   auto* m43 = p->ConvertType(43);
-  EXPECT_TRUE(m43->IsMatrix());
-  EXPECT_TRUE(m43->AsMatrix()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(m43->AsMatrix()->rows(), 4u);
-  EXPECT_EQ(m43->AsMatrix()->columns(), 3u);
+  EXPECT_TRUE(m43->Is<ast::type::MatrixType>());
+  EXPECT_TRUE(
+      m43->As<ast::type::MatrixType>()->type()->Is<ast::type::F32Type>());
+  EXPECT_EQ(m43->As<ast::type::MatrixType>()->rows(), 4u);
+  EXPECT_EQ(m43->As<ast::type::MatrixType>()->columns(), 3u);
 
   auto* m44 = p->ConvertType(44);
-  EXPECT_TRUE(m44->IsMatrix());
-  EXPECT_TRUE(m44->AsMatrix()->type()->Is<ast::type::F32Type>());
-  EXPECT_EQ(m44->AsMatrix()->rows(), 4u);
-  EXPECT_EQ(m44->AsMatrix()->columns(), 4u);
+  EXPECT_TRUE(m44->Is<ast::type::MatrixType>());
+  EXPECT_TRUE(
+      m44->As<ast::type::MatrixType>()->type()->Is<ast::type::F32Type>());
+  EXPECT_EQ(m44->As<ast::type::MatrixType>()->rows(), 4u);
+  EXPECT_EQ(m44->As<ast::type::MatrixType>()->columns(), 4u);
 
   EXPECT_TRUE(p->error().empty());
 }
diff --git a/src/reader/wgsl/parser_impl_type_decl_test.cc b/src/reader/wgsl/parser_impl_type_decl_test.cc
index 7d30582..b64fbb8 100644
--- a/src/reader/wgsl/parser_impl_type_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_type_decl_test.cc
@@ -621,8 +621,8 @@
   EXPECT_FALSE(t.errored);
   ASSERT_NE(t.value, nullptr) << p->error();
   ASSERT_FALSE(p->has_error());
-  EXPECT_TRUE(t->IsMatrix());
-  auto* mat = t->AsMatrix();
+  EXPECT_TRUE(t->Is<ast::type::MatrixType>());
+  auto* mat = t->As<ast::type::MatrixType>();
   EXPECT_EQ(mat->rows(), params.rows);
   EXPECT_EQ(mat->columns(), params.columns);
 }
diff --git a/src/transform/bound_array_accessors_transform.cc b/src/transform/bound_array_accessors_transform.cc
index 41d4459..dd9ec6f 100644
--- a/src/transform/bound_array_accessors_transform.cc
+++ b/src/transform/bound_array_accessors_transform.cc
@@ -184,8 +184,8 @@
   }
 
   auto* ret_type = expr->array()->result_type()->UnwrapAll();
-  if (!ret_type->Is<ast::type::ArrayType>() && !ret_type->IsMatrix() &&
-      !ret_type->IsVector()) {
+  if (!ret_type->Is<ast::type::ArrayType>() &&
+      !ret_type->Is<ast::type::MatrixType>() && !ret_type->IsVector()) {
     return true;
   }
 
@@ -204,7 +204,7 @@
   } else {
     // The row accessor would have been an embedded array accessor and already
     // handled, so we just need to do columns here.
-    uint32_t size = ret_type->AsMatrix()->columns();
+    uint32_t size = ret_type->As<ast::type::MatrixType>()->columns();
     if (!ProcessAccessExpression(expr, size)) {
       return false;
     }
diff --git a/src/type_determiner.cc b/src/type_determiner.cc
index 627138c..e77d082 100644
--- a/src/type_determiner.cc
+++ b/src/type_determiner.cc
@@ -337,8 +337,8 @@
     ret = parent_type->As<ast::type::ArrayType>()->type();
   } else if (parent_type->IsVector()) {
     ret = parent_type->AsVector()->type();
-  } else if (parent_type->IsMatrix()) {
-    auto* m = parent_type->AsMatrix();
+  } else if (parent_type->Is<ast::type::MatrixType>()) {
+    auto* m = parent_type->As<ast::type::MatrixType>();
     ret = mod_->create<ast::type::VectorType>(m->type(), m->rows());
   } else {
     set_error(expr->source(), "invalid parent type (" +
@@ -790,7 +790,7 @@
         }
         break;
       case IntrinsicDataType::kMatrix:
-        if (!result_types.back()->IsMatrix()) {
+        if (!result_types.back()->Is<ast::type::MatrixType>()) {
           set_error(expr->source(), "incorrect type for " + ident->name() +
                                         ". Requires matrix value");
           return false;
@@ -819,7 +819,8 @@
   }
   // The determinant returns the component type of the columns
   if (ident->intrinsic() == ast::Intrinsic::kDeterminant) {
-    expr->func()->set_result_type(result_types[0]->AsMatrix()->type());
+    expr->func()->set_result_type(
+        result_types[0]->As<ast::type::MatrixType>()->type());
     return true;
   }
   expr->func()->set_result_type(result_types[0]);
@@ -1111,23 +1112,25 @@
 
     // Note, the ordering here matters. The later checks depend on the prior
     // checks having been done.
-    if (lhs_type->IsMatrix() && rhs_type->IsMatrix()) {
+    if (lhs_type->Is<ast::type::MatrixType>() &&
+        rhs_type->Is<ast::type::MatrixType>()) {
       expr->set_result_type(mod_->create<ast::type::MatrixType>(
-          lhs_type->AsMatrix()->type(), lhs_type->AsMatrix()->rows(),
-          rhs_type->AsMatrix()->columns()));
+          lhs_type->As<ast::type::MatrixType>()->type(),
+          lhs_type->As<ast::type::MatrixType>()->rows(),
+          rhs_type->As<ast::type::MatrixType>()->columns()));
 
-    } else if (lhs_type->IsMatrix() && rhs_type->IsVector()) {
-      auto* mat = lhs_type->AsMatrix();
+    } else if (lhs_type->Is<ast::type::MatrixType>() && rhs_type->IsVector()) {
+      auto* mat = lhs_type->As<ast::type::MatrixType>();
       expr->set_result_type(
           mod_->create<ast::type::VectorType>(mat->type(), mat->rows()));
-    } else if (lhs_type->IsVector() && rhs_type->IsMatrix()) {
-      auto* mat = rhs_type->AsMatrix();
+    } else if (lhs_type->IsVector() && rhs_type->Is<ast::type::MatrixType>()) {
+      auto* mat = rhs_type->As<ast::type::MatrixType>();
       expr->set_result_type(
           mod_->create<ast::type::VectorType>(mat->type(), mat->columns()));
-    } else if (lhs_type->IsMatrix()) {
+    } else if (lhs_type->Is<ast::type::MatrixType>()) {
       // matrix * scalar
       expr->set_result_type(lhs_type);
-    } else if (rhs_type->IsMatrix()) {
+    } else if (rhs_type->Is<ast::type::MatrixType>()) {
       // scalar * matrix
       expr->set_result_type(rhs_type);
     } else if (lhs_type->IsVector() && rhs_type->IsVector()) {
diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc
index f3c8735..4a928b9 100644
--- a/src/type_determiner_test.cc
+++ b/src/type_determiner_test.cc
@@ -1385,9 +1385,9 @@
 
   ASSERT_TRUE(td()->DetermineResultType(&expr)) << td()->error();
   ASSERT_NE(expr.result_type(), nullptr);
-  ASSERT_TRUE(expr.result_type()->IsMatrix());
+  ASSERT_TRUE(expr.result_type()->Is<ast::type::MatrixType>());
 
-  auto* mat = expr.result_type()->AsMatrix();
+  auto* mat = expr.result_type()->As<ast::type::MatrixType>();
   EXPECT_TRUE(mat->type()->Is<ast::type::F32Type>());
   EXPECT_EQ(mat->rows(), 3u);
   EXPECT_EQ(mat->columns(), 2u);
@@ -1413,9 +1413,9 @@
 
   ASSERT_TRUE(td()->DetermineResultType(&expr)) << td()->error();
   ASSERT_NE(expr.result_type(), nullptr);
-  ASSERT_TRUE(expr.result_type()->IsMatrix());
+  ASSERT_TRUE(expr.result_type()->Is<ast::type::MatrixType>());
 
-  auto* mat = expr.result_type()->AsMatrix();
+  auto* mat = expr.result_type()->As<ast::type::MatrixType>();
   EXPECT_TRUE(mat->type()->Is<ast::type::F32Type>());
   EXPECT_EQ(mat->rows(), 3u);
   EXPECT_EQ(mat->columns(), 2u);
@@ -1494,9 +1494,9 @@
 
   ASSERT_TRUE(td()->DetermineResultType(&expr)) << td()->error();
   ASSERT_NE(expr.result_type(), nullptr);
-  ASSERT_TRUE(expr.result_type()->IsMatrix());
+  ASSERT_TRUE(expr.result_type()->Is<ast::type::MatrixType>());
 
-  auto* mat = expr.result_type()->AsMatrix();
+  auto* mat = expr.result_type()->As<ast::type::MatrixType>();
   EXPECT_TRUE(mat->type()->Is<ast::type::F32Type>());
   EXPECT_EQ(mat->rows(), 4u);
   EXPECT_EQ(mat->columns(), 4u);
@@ -2018,9 +2018,9 @@
   EXPECT_TRUE(td()->DetermineResultType(&expr));
 
   ASSERT_NE(expr.result_type(), nullptr);
-  ASSERT_TRUE(expr.result_type()->IsMatrix());
+  ASSERT_TRUE(expr.result_type()->Is<ast::type::MatrixType>());
 
-  auto* mat = expr.result_type()->AsMatrix();
+  auto* mat = expr.result_type()->As<ast::type::MatrixType>();
   EXPECT_TRUE(mat->type()->Is<ast::type::F32Type>());
   EXPECT_EQ(mat->rows(), 3u);
   EXPECT_EQ(mat->columns(), 2u);
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index e1db5d0..782f471 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -373,9 +373,10 @@
   // Multiplying by a matrix requires the use of `mul` in order to get the
   // type of multiply we desire.
   if (expr->op() == ast::BinaryOp::kMultiply &&
-      ((lhs_type->IsVector() && rhs_type->IsMatrix()) ||
-       (lhs_type->IsMatrix() && rhs_type->IsVector()) ||
-       (lhs_type->IsMatrix() && rhs_type->IsMatrix()))) {
+      ((lhs_type->IsVector() && rhs_type->Is<ast::type::MatrixType>()) ||
+       (lhs_type->Is<ast::type::MatrixType>() && rhs_type->IsVector()) ||
+       (lhs_type->Is<ast::type::MatrixType>() &&
+        rhs_type->Is<ast::type::MatrixType>()))) {
     out << "mul(";
     if (!EmitExpression(pre, out, expr->lhs())) {
       return false;
@@ -1553,8 +1554,8 @@
     out << "0u";
   } else if (type->IsVector()) {
     return EmitZeroValue(out, type->AsVector()->type());
-  } else if (type->IsMatrix()) {
-    auto* mat = type->AsMatrix();
+  } else if (type->Is<ast::type::MatrixType>()) {
+    auto* mat = type->As<ast::type::MatrixType>();
     for (uint32_t i = 0; i < (mat->rows() * mat->columns()); i++) {
       if (i != 0) {
         out << ", ";
@@ -1726,8 +1727,8 @@
         // or u32 which are all 4 bytes. When we get f16 or other types we'll
         // have to ask the type for the byte size.
         out << "4";
-      } else if (ary_type->IsMatrix()) {
-        auto* mat = ary_type->AsMatrix();
+      } else if (ary_type->Is<ast::type::MatrixType>()) {
+        auto* mat = ary_type->As<ast::type::MatrixType>();
         if (mat->columns() == 2) {
           out << "8";
         } else {
@@ -1770,13 +1771,15 @@
   std::string access_method = is_store ? "Store" : "Load";
   if (result_type->IsVector()) {
     access_method += std::to_string(result_type->AsVector()->size());
-  } else if (result_type->IsMatrix()) {
-    access_method += std::to_string(result_type->AsMatrix()->rows());
+  } else if (result_type->Is<ast::type::MatrixType>()) {
+    access_method +=
+        std::to_string(result_type->As<ast::type::MatrixType>()->rows());
   }
 
   // If we aren't storing then we need to put in the outer cast.
   if (!is_store) {
-    if (result_type->is_float_scalar_or_vector() || result_type->IsMatrix()) {
+    if (result_type->is_float_scalar_or_vector() ||
+        result_type->Is<ast::type::MatrixType>()) {
       out << "asfloat(";
     } else if (result_type->is_signed_scalar_or_vector()) {
       out << "asint(";
@@ -1796,8 +1799,8 @@
     return false;
   }
 
-  if (result_type->IsMatrix()) {
-    auto* mat = result_type->AsMatrix();
+  if (result_type->Is<ast::type::MatrixType>()) {
+    auto* mat = result_type->As<ast::type::MatrixType>();
 
     // TODO(dsinclair): This is assuming 4 byte elements. Will need to be fixed
     // if we get matrixes of f16 or f64.
@@ -2064,8 +2067,8 @@
     out << "float";
   } else if (type->Is<ast::type::I32Type>()) {
     out << "int";
-  } else if (type->IsMatrix()) {
-    auto* mat = type->AsMatrix();
+  } else if (type->Is<ast::type::MatrixType>()) {
+    auto* mat = type->As<ast::type::MatrixType>();
     if (!EmitType(out, mat->type(), "")) {
       return false;
     }
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index 8d85591..3404522 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -204,8 +204,8 @@
       type->IsU32()) {
     return 4;
   }
-  if (type->IsMatrix()) {
-    auto* mat = type->AsMatrix();
+  if (type->Is<ast::type::MatrixType>()) {
+    auto* mat = type->As<ast::type::MatrixType>();
     // TODO(dsinclair): Handle MatrixStride
     // https://github.com/gpuweb/gpuweb/issues/773
     uint32_t type_size = calculate_alignment_size(mat->type());
@@ -939,8 +939,8 @@
     out_ << "0u";
   } else if (type->IsVector()) {
     return EmitZeroValue(type->AsVector()->type());
-  } else if (type->IsMatrix()) {
-    return EmitZeroValue(type->AsMatrix()->type());
+  } else if (type->Is<ast::type::MatrixType>()) {
+    return EmitZeroValue(type->As<ast::type::MatrixType>()->type());
   } else if (type->Is<ast::type::ArrayType>()) {
     out_ << "{";
     if (!EmitZeroValue(type->As<ast::type::ArrayType>()->type())) {
@@ -1819,8 +1819,8 @@
     out_ << "float";
   } else if (type->Is<ast::type::I32Type>()) {
     out_ << "int";
-  } else if (type->IsMatrix()) {
-    auto* mat = type->AsMatrix();
+  } else if (type->Is<ast::type::MatrixType>()) {
+    auto* mat = type->As<ast::type::MatrixType>();
     if (!EmitType(mat->type(), "")) {
       return false;
     }
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index e7efa82..4327476 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -150,7 +150,8 @@
   while (type->Is<ast::type::ArrayType>()) {
     type = type->As<ast::type::ArrayType>()->type();
   }
-  return type->IsMatrix() ? type->AsMatrix() : nullptr;
+  return type->Is<ast::type::MatrixType>() ? type->As<ast::type::MatrixType>()
+                                           : nullptr;
 }
 
 uint32_t intrinsic_to_glsl_method(ast::type::Type* type,
@@ -1203,8 +1204,8 @@
     ast::type::Type* subtype = result_type->UnwrapAll();
     if (subtype->IsVector()) {
       subtype = subtype->AsVector()->type()->UnwrapAll();
-    } else if (subtype->IsMatrix()) {
-      subtype = subtype->AsMatrix()->type()->UnwrapAll();
+    } else if (subtype->Is<ast::type::MatrixType>()) {
+      subtype = subtype->As<ast::type::MatrixType>()->type()->UnwrapAll();
     } else if (subtype->Is<ast::type::ArrayType>()) {
       subtype = subtype->As<ast::type::ArrayType>()->type()->UnwrapAll();
     } else if (subtype->IsStruct()) {
@@ -1280,7 +1281,7 @@
     // If the result and value types are the same we can just use the object.
     // If the result is not a vector then we should have validated that the
     // value type is a correctly sized vector so we can just use it directly.
-    if (result_type == value_type || result_type->IsMatrix() ||
+    if (result_type == value_type || result_type->Is<ast::type::MatrixType>() ||
         result_type->Is<ast::type::ArrayType>() || result_type->IsStruct()) {
       out << "_" << id;
 
@@ -2426,8 +2427,8 @@
     push_type(spv::Op::OpTypeFloat, {result, Operand::Int(32)});
   } else if (type->Is<ast::type::I32Type>()) {
     push_type(spv::Op::OpTypeInt, {result, Operand::Int(32), Operand::Int(1)});
-  } else if (type->IsMatrix()) {
-    if (!GenerateMatrixType(type->AsMatrix(), result)) {
+  } else if (type->Is<ast::type::MatrixType>()) {
+    if (!GenerateMatrixType(type->As<ast::type::MatrixType>(), result)) {
       return 0;
     }
   } else if (type->IsPointer()) {
diff --git a/src/writer/spirv/builder.h b/src/writer/spirv/builder.h
index fc0685c..bda42b6 100644
--- a/src/writer/spirv/builder.h
+++ b/src/writer/spirv/builder.h
@@ -27,8 +27,9 @@
 #include "src/ast/literal.h"
 #include "src/ast/module.h"
 #include "src/ast/struct_member.h"
-#include "src/ast/type/array_type.h"
 #include "src/ast/type/access_control_type.h"
+#include "src/ast/type/array_type.h"
+#include "src/ast/type/matrix_type.h"
 #include "src/ast/type/storage_texture_type.h"
 #include "src/ast/type_constructor_expression.h"
 #include "src/context.h"
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc
index e7a65e8..1ecfec3 100644
--- a/src/writer/wgsl/generator_impl.cc
+++ b/src/writer/wgsl/generator_impl.cc
@@ -439,8 +439,8 @@
     out_ << "f32";
   } else if (type->Is<ast::type::I32Type>()) {
     out_ << "i32";
-  } else if (type->IsMatrix()) {
-    auto* mat = type->AsMatrix();
+  } else if (type->Is<ast::type::MatrixType>()) {
+    auto* mat = type->As<ast::type::MatrixType>();
     out_ << "mat" << mat->columns() << "x" << mat->rows() << "<";
     if (!EmitType(mat->type())) {
       return false;