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

Change-Id: Id130581f72e762bd398a4c1c509cdbe21739e750
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/34267
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/ast/expression_test.cc b/src/ast/expression_test.cc
index a1b6881..b651b01 100644
--- a/src/ast/expression_test.cc
+++ b/src/ast/expression_test.cc
@@ -38,7 +38,7 @@
   Expr e;
   e.set_result_type(&i32);
   ASSERT_NE(e.result_type(), nullptr);
-  EXPECT_TRUE(e.result_type()->IsI32());
+  EXPECT_TRUE(e.result_type()->Is<ast::type::I32Type>());
 }
 
 TEST_F(ExpressionTest, set_result_type_alias) {
@@ -49,7 +49,7 @@
   Expr e;
   e.set_result_type(&b);
   ASSERT_NE(e.result_type(), nullptr);
-  EXPECT_TRUE(e.result_type()->IsI32());
+  EXPECT_TRUE(e.result_type()->Is<ast::type::I32Type>());
 }
 
 }  // namespace
diff --git a/src/ast/type/access_control_type_test.cc b/src/ast/type/access_control_type_test.cc
index 389f7f8..24d908b 100644
--- a/src/ast/type/access_control_type_test.cc
+++ b/src/ast/type/access_control_type_test.cc
@@ -55,7 +55,7 @@
   EXPECT_FALSE(ty->Is<ArrayType>());
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
-  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->Is<I32Type>());
   EXPECT_FALSE(ty->IsMatrix());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
diff --git a/src/ast/type/alias_type_test.cc b/src/ast/type/alias_type_test.cc
index 26b1b32..7e76f80 100644
--- a/src/ast/type/alias_type_test.cc
+++ b/src/ast/type/alias_type_test.cc
@@ -56,7 +56,7 @@
   EXPECT_FALSE(ty->Is<ArrayType>());
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
-  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->Is<I32Type>());
   EXPECT_FALSE(ty->IsMatrix());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
diff --git a/src/ast/type/array_type_test.cc b/src/ast/type/array_type_test.cc
index 19f7d1a..5c9bbfa 100644
--- a/src/ast/type/array_type_test.cc
+++ b/src/ast/type/array_type_test.cc
@@ -60,7 +60,7 @@
   EXPECT_TRUE(ty->Is<ArrayType>());
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
-  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->Is<I32Type>());
   EXPECT_FALSE(ty->IsMatrix());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
diff --git a/src/ast/type/bool_type_test.cc b/src/ast/type/bool_type_test.cc
index fffa7d7..a04d882 100644
--- a/src/ast/type/bool_type_test.cc
+++ b/src/ast/type/bool_type_test.cc
@@ -18,6 +18,7 @@
 #include "src/ast/type/access_control_type.h"
 #include "src/ast/type/array_type.h"
 #include "src/ast/type/f32_type.h"
+#include "src/ast/type/i32_type.h"
 
 namespace tint {
 namespace ast {
@@ -34,7 +35,7 @@
   EXPECT_FALSE(ty->Is<ArrayType>());
   EXPECT_TRUE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
-  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->Is<I32Type>());
   EXPECT_FALSE(ty->IsMatrix());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
diff --git a/src/ast/type/depth_texture_type_test.cc b/src/ast/type/depth_texture_type_test.cc
index 1bc6e15..af8231a 100644
--- a/src/ast/type/depth_texture_type_test.cc
+++ b/src/ast/type/depth_texture_type_test.cc
@@ -20,6 +20,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/i32_type.h"
 
 namespace tint {
 namespace ast {
@@ -36,7 +37,7 @@
   EXPECT_FALSE(ty->Is<ArrayType>());
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
-  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->Is<I32Type>());
   EXPECT_FALSE(ty->IsMatrix());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
diff --git a/src/ast/type/f32_type_test.cc b/src/ast/type/f32_type_test.cc
index 718df7b..1cf54b3 100644
--- a/src/ast/type/f32_type_test.cc
+++ b/src/ast/type/f32_type_test.cc
@@ -18,6 +18,7 @@
 #include "src/ast/type/access_control_type.h"
 #include "src/ast/type/array_type.h"
 #include "src/ast/type/bool_type.h"
+#include "src/ast/type/i32_type.h"
 
 namespace tint {
 namespace ast {
@@ -34,7 +35,7 @@
   EXPECT_FALSE(ty->Is<ArrayType>());
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_TRUE(ty->Is<F32Type>());
-  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->Is<I32Type>());
   EXPECT_FALSE(ty->IsMatrix());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
diff --git a/src/ast/type/i32_type.cc b/src/ast/type/i32_type.cc
index 04ad5aa..c3c2838 100644
--- a/src/ast/type/i32_type.cc
+++ b/src/ast/type/i32_type.cc
@@ -24,10 +24,6 @@
 
 I32Type::~I32Type() = default;
 
-bool I32Type::IsI32() const {
-  return true;
-}
-
 std::string I32Type::type_name() const {
   return "__i32";
 }
diff --git a/src/ast/type/i32_type.h b/src/ast/type/i32_type.h
index 873e7b4..e1b9d9f 100644
--- a/src/ast/type/i32_type.h
+++ b/src/ast/type/i32_type.h
@@ -32,9 +32,6 @@
   I32Type(I32Type&&);
   ~I32Type() override;
 
-  /// @returns true if the type is an i32 type
-  bool IsI32() const override;
-
   /// @returns the name for this type
   std::string type_name() const override;
 
diff --git a/src/ast/type/i32_type_test.cc b/src/ast/type/i32_type_test.cc
index e41c2fb..340447a 100644
--- a/src/ast/type/i32_type_test.cc
+++ b/src/ast/type/i32_type_test.cc
@@ -35,7 +35,7 @@
   EXPECT_FALSE(ty->Is<ArrayType>());
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
-  EXPECT_TRUE(ty->IsI32());
+  EXPECT_TRUE(ty->Is<I32Type>());
   EXPECT_FALSE(ty->IsMatrix());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
diff --git a/src/ast/type/matrix_type_test.cc b/src/ast/type/matrix_type_test.cc
index ae207e9..42d02d0 100644
--- a/src/ast/type/matrix_type_test.cc
+++ b/src/ast/type/matrix_type_test.cc
@@ -45,7 +45,7 @@
   EXPECT_FALSE(ty->Is<ArrayType>());
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
-  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->Is<I32Type>());
   EXPECT_TRUE(ty->IsMatrix());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
diff --git a/src/ast/type/multisampled_texture_type_test.cc b/src/ast/type/multisampled_texture_type_test.cc
index c9d5919..0f52be4 100644
--- a/src/ast/type/multisampled_texture_type_test.cc
+++ b/src/ast/type/multisampled_texture_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/i32_type.h"
 
 namespace tint {
 namespace ast {
@@ -36,7 +37,7 @@
   EXPECT_FALSE(ty->Is<ArrayType>());
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
-  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->Is<I32Type>());
   EXPECT_FALSE(ty->IsMatrix());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
diff --git a/src/ast/type/pointer_type_test.cc b/src/ast/type/pointer_type_test.cc
index 755d6ae..420a10b 100644
--- a/src/ast/type/pointer_type_test.cc
+++ b/src/ast/type/pointer_type_test.cc
@@ -44,7 +44,7 @@
   EXPECT_FALSE(ty->Is<ArrayType>());
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
-  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->Is<I32Type>());
   EXPECT_FALSE(ty->IsMatrix());
   EXPECT_TRUE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
diff --git a/src/ast/type/sampled_texture_type_test.cc b/src/ast/type/sampled_texture_type_test.cc
index 845735d..6e1cbbd 100644
--- a/src/ast/type/sampled_texture_type_test.cc
+++ b/src/ast/type/sampled_texture_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/i32_type.h"
 
 namespace tint {
 namespace ast {
@@ -36,7 +37,7 @@
   EXPECT_FALSE(ty->Is<ArrayType>());
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
-  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->Is<I32Type>());
   EXPECT_FALSE(ty->IsMatrix());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
diff --git a/src/ast/type/sampler_type_test.cc b/src/ast/type/sampler_type_test.cc
index d895bbb..41dcfea 100644
--- a/src/ast/type/sampler_type_test.cc
+++ b/src/ast/type/sampler_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/i32_type.h"
 
 namespace tint {
 namespace ast {
@@ -46,7 +47,7 @@
   EXPECT_FALSE(ty->Is<ArrayType>());
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
-  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->Is<I32Type>());
   EXPECT_FALSE(ty->IsMatrix());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_TRUE(ty->IsSampler());
diff --git a/src/ast/type/storage_texture_type_test.cc b/src/ast/type/storage_texture_type_test.cc
index 4e9277a..780e316 100644
--- a/src/ast/type/storage_texture_type_test.cc
+++ b/src/ast/type/storage_texture_type_test.cc
@@ -22,6 +22,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/i32_type.h"
 #include "src/type_determiner.h"
 
 namespace tint {
@@ -40,7 +41,7 @@
   EXPECT_FALSE(ty->Is<ArrayType>());
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
-  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->Is<I32Type>());
   EXPECT_FALSE(ty->IsMatrix());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
@@ -93,7 +94,7 @@
   ASSERT_TRUE(td.Determine()) << td.error();
   ASSERT_TRUE(s->IsTexture());
   ASSERT_TRUE(s->AsTexture()->IsStorage());
-  EXPECT_TRUE(s->AsTexture()->AsStorage()->type()->Is<ast::type::F32Type>());
+  EXPECT_TRUE(s->AsTexture()->AsStorage()->type()->Is<F32Type>());
 }
 
 TEST_F(StorageTextureTypeTest, U32Type) {
@@ -121,7 +122,7 @@
   ASSERT_TRUE(td.Determine()) << td.error();
   ASSERT_TRUE(s->IsTexture());
   ASSERT_TRUE(s->AsTexture()->IsStorage());
-  EXPECT_TRUE(s->AsTexture()->AsStorage()->type()->IsI32());
+  EXPECT_TRUE(s->AsTexture()->AsStorage()->type()->Is<I32Type>());
 }
 
 TEST_F(StorageTextureTypeTest, MinBufferBindingSize) {
diff --git a/src/ast/type/struct_type_test.cc b/src/ast/type/struct_type_test.cc
index 94aef60..8e382bd 100644
--- a/src/ast/type/struct_type_test.cc
+++ b/src/ast/type/struct_type_test.cc
@@ -52,7 +52,7 @@
   EXPECT_FALSE(ty->Is<ArrayType>());
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
-  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->Is<I32Type>());
   EXPECT_FALSE(ty->IsMatrix());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
diff --git a/src/ast/type/type.cc b/src/ast/type/type.cc
index e6377ce..c496356 100644
--- a/src/ast/type/type.cc
+++ b/src/ast/type/type.cc
@@ -66,10 +66,6 @@
   return UnwrapIfNeeded()->UnwrapPtrIfNeeded()->UnwrapIfNeeded();
 }
 
-bool Type::IsI32() const {
-  return false;
-}
-
 bool Type::IsMatrix() const {
   return false;
 }
@@ -131,7 +127,7 @@
 }
 
 bool Type::is_integer_scalar() {
-  return IsU32() || IsI32();
+  return IsU32() || Is<I32Type>();
 }
 
 bool Type::is_unsigned_integer_vector() {
@@ -139,7 +135,7 @@
 }
 
 bool Type::is_signed_integer_vector() {
-  return IsVector() && AsVector()->type()->IsI32();
+  return IsVector() && AsVector()->type()->Is<I32Type>();
 }
 
 bool Type::is_unsigned_scalar_or_vector() {
@@ -147,18 +143,13 @@
 }
 
 bool Type::is_signed_scalar_or_vector() {
-  return IsI32() || (IsVector() && AsVector()->type()->IsI32());
+  return Is<I32Type>() || (IsVector() && AsVector()->type()->Is<I32Type>());
 }
 
 bool Type::is_integer_scalar_or_vector() {
   return is_unsigned_scalar_or_vector() || is_signed_scalar_or_vector();
 }
 
-const I32Type* Type::AsI32() const {
-  assert(IsI32());
-  return static_cast<const I32Type*>(this);
-}
-
 const MatrixType* Type::AsMatrix() const {
   assert(IsMatrix());
   return static_cast<const MatrixType*>(this);
@@ -199,11 +190,6 @@
   return static_cast<const VoidType*>(this);
 }
 
-I32Type* Type::AsI32() {
-  assert(IsI32());
-  return static_cast<I32Type*>(this);
-}
-
 MatrixType* Type::AsMatrix() {
   assert(IsMatrix());
   return static_cast<MatrixType*>(this);
diff --git a/src/ast/type/type.h b/src/ast/type/type.h
index fff6457..4fd931e 100644
--- a/src/ast/type/type.h
+++ b/src/ast/type/type.h
@@ -23,7 +23,6 @@
 namespace ast {
 namespace type {
 
-class I32Type;
 class MatrixType;
 class PointerType;
 class SamplerType;
@@ -43,8 +42,6 @@
   Type(Type&&);
   ~Type() override;
 
-  /// @returns true if the type is an i32 type
-  virtual bool IsI32() const;
   /// @returns true if the type is a matrix type
   virtual bool IsMatrix() const;
   /// @returns true if the type is a ptr type
@@ -116,8 +113,6 @@
   /// @returns true if this type is an integer scalar or vector
   bool is_integer_scalar_or_vector();
 
-  /// @returns the type as an i32 type
-  const I32Type* AsI32() const;
   /// @returns the type as a matrix type
   const MatrixType* AsMatrix() const;
   /// @returns the type as a pointer type
@@ -135,8 +130,6 @@
   /// @returns the type as a void type
   const VoidType* AsVoid() const;
 
-  /// @returns the type as an i32 type
-  I32Type* AsI32();
   /// @returns the type as a matrix type
   MatrixType* AsMatrix();
   /// @returns the type as a pointer type
diff --git a/src/ast/type/u32_type_test.cc b/src/ast/type/u32_type_test.cc
index 98ab357..963d3bc 100644
--- a/src/ast/type/u32_type_test.cc
+++ b/src/ast/type/u32_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/i32_type.h"
 
 namespace tint {
 namespace ast {
@@ -35,7 +36,7 @@
   EXPECT_FALSE(ty->Is<ArrayType>());
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
-  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->Is<I32Type>());
   EXPECT_FALSE(ty->IsMatrix());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
diff --git a/src/ast/type/vector_type_test.cc b/src/ast/type/vector_type_test.cc
index d5491bf..9c9d930 100644
--- a/src/ast/type/vector_type_test.cc
+++ b/src/ast/type/vector_type_test.cc
@@ -44,7 +44,7 @@
   EXPECT_FALSE(ty->Is<ArrayType>());
   EXPECT_FALSE(ty->Is<BoolType>());
   EXPECT_FALSE(ty->Is<F32Type>());
-  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->Is<I32Type>());
   EXPECT_FALSE(ty->IsMatrix());
   EXPECT_FALSE(ty->IsPointer());
   EXPECT_FALSE(ty->IsSampler());
diff --git a/src/ast/type_manager_test.cc b/src/ast/type_manager_test.cc
index 4bbd9a9..bc321c3 100644
--- a/src/ast/type_manager_test.cc
+++ b/src/ast/type_manager_test.cc
@@ -28,14 +28,14 @@
   ast::TypeManager tm;
   auto* t = tm.Get(std::make_unique<ast::type::I32Type>());
   ASSERT_NE(t, nullptr);
-  EXPECT_TRUE(t->IsI32());
+  EXPECT_TRUE(t->Is<ast::type::I32Type>());
 }
 
 TEST_F(TypeManagerTest, GetSameTypeReturnsSamePtr) {
   ast::TypeManager tm;
   auto* t = tm.Get(std::make_unique<ast::type::I32Type>());
   ASSERT_NE(t, nullptr);
-  EXPECT_TRUE(t->IsI32());
+  EXPECT_TRUE(t->Is<ast::type::I32Type>());
 
   auto* t2 = tm.Get(std::make_unique<ast::type::I32Type>());
   EXPECT_EQ(t, t2);
@@ -45,7 +45,7 @@
   ast::TypeManager tm;
   auto* t = tm.Get(std::make_unique<ast::type::I32Type>());
   ASSERT_NE(t, nullptr);
-  EXPECT_TRUE(t->IsI32());
+  EXPECT_TRUE(t->Is<ast::type::I32Type>());
 
   auto* t2 = tm.Get(std::make_unique<ast::type::U32Type>());
   ASSERT_NE(t2, nullptr);
diff --git a/src/inspector/inspector.cc b/src/inspector/inspector.cc
index f891d7c..ae58e43 100644
--- a/src/inspector/inspector.cc
+++ b/src/inspector/inspector.cc
@@ -29,6 +29,7 @@
 #include "src/ast/type/access_control_type.h"
 #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"
 #include "src/ast/type/multisampled_texture_type.h"
 #include "src/ast/type/sampled_texture_type.h"
@@ -396,7 +397,7 @@
       entry.sampled_kind = ResourceBinding::SampledKind::kFloat;
     } else if (base_type->IsU32()) {
       entry.sampled_kind = ResourceBinding::SampledKind::kUInt;
-    } else if (base_type->IsI32()) {
+    } else if (base_type->Is<ast::type::I32Type>()) {
       entry.sampled_kind = ResourceBinding::SampledKind::kSInt;
     } else {
       entry.sampled_kind = ResourceBinding::SampledKind::kUnknown;
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index 4edcfd5..0ba75d1 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -975,7 +975,7 @@
       case SpvOpSpecConstant: {
         ast_type = ConvertType(inst.type_id());
         const uint32_t literal_value = inst.GetSingleWordInOperand(0);
-        if (ast_type->IsI32()) {
+        if (ast_type->Is<ast::type::I32Type>()) {
           ast_expr =
               create<ast::ScalarConstructorExpression>(create<ast::SintLiteral>(
                   ast_type, static_cast<int32_t>(literal_value)));
@@ -1267,7 +1267,7 @@
             create<ast::ScalarConstructorExpression>(
                 create<ast::UintLiteral>(ast_type, spirv_const->GetU32()))};
   }
-  if (ast_type->IsI32()) {
+  if (ast_type->Is<ast::type::I32Type>()) {
     return {ast_type,
             create<ast::ScalarConstructorExpression>(
                 create<ast::SintLiteral>(ast_type, spirv_const->GetS32()))};
@@ -1342,7 +1342,7 @@
     return create<ast::ScalarConstructorExpression>(
         create<ast::UintLiteral>(type, 0u));
   }
-  if (type->IsI32()) {
+  if (type->Is<ast::type::I32Type>()) {
     return create<ast::ScalarConstructorExpression>(
         create<ast::SintLiteral>(type, 0));
   }
@@ -1445,7 +1445,8 @@
     Fail() << "no type provided";
   }
   auto* i32 = ast_module_.create<ast::type::I32Type>();
-  if (other->Is<ast::type::F32Type>() || other->IsU32() || other->IsI32()) {
+  if (other->Is<ast::type::F32Type>() || other->IsU32() ||
+      other->Is<ast::type::I32Type>()) {
     return i32;
   }
   auto* vec_ty = other->AsVector();
@@ -1463,7 +1464,8 @@
     return nullptr;
   }
   auto* u32 = ast_module_.create<ast::type::U32Type>();
-  if (other->Is<ast::type::F32Type>() || other->IsU32() || other->IsI32()) {
+  if (other->Is<ast::type::F32Type>() || other->IsU32() ||
+      other->Is<ast::type::I32Type>()) {
     return u32;
   }
   auto* vec_ty = other->AsVector();
diff --git a/src/reader/spirv/parser_impl_convert_type_test.cc b/src/reader/spirv/parser_impl_convert_type_test.cc
index 0c3e9da..4893bb1 100644
--- a/src/reader/spirv/parser_impl_convert_type_test.cc
+++ b/src/reader/spirv/parser_impl_convert_type_test.cc
@@ -21,6 +21,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/i32_type.h"
 #include "src/ast/type/matrix_type.h"
 #include "src/ast/type/pointer_type.h"
 #include "src/ast/type/struct_type.h"
@@ -107,7 +108,7 @@
   EXPECT_TRUE(p->BuildInternalModule());
 
   auto* type = p->ConvertType(2);
-  EXPECT_TRUE(type->IsI32());
+  EXPECT_TRUE(type->Is<ast::type::I32Type>());
   EXPECT_TRUE(p->error().empty());
 }
 
@@ -197,17 +198,17 @@
 
   auto* v2xi32 = p->ConvertType(20);
   EXPECT_TRUE(v2xi32->IsVector());
-  EXPECT_TRUE(v2xi32->AsVector()->type()->IsI32());
+  EXPECT_TRUE(v2xi32->AsVector()->type()->Is<ast::type::I32Type>());
   EXPECT_EQ(v2xi32->AsVector()->size(), 2u);
 
   auto* v3xi32 = p->ConvertType(30);
   EXPECT_TRUE(v3xi32->IsVector());
-  EXPECT_TRUE(v3xi32->AsVector()->type()->IsI32());
+  EXPECT_TRUE(v3xi32->AsVector()->type()->Is<ast::type::I32Type>());
   EXPECT_EQ(v3xi32->AsVector()->size(), 3u);
 
   auto* v4xi32 = p->ConvertType(40);
   EXPECT_TRUE(v4xi32->IsVector());
-  EXPECT_TRUE(v4xi32->AsVector()->type()->IsI32());
+  EXPECT_TRUE(v4xi32->AsVector()->type()->Is<ast::type::I32Type>());
   EXPECT_EQ(v4xi32->AsVector()->size(), 4u);
 
   EXPECT_TRUE(p->error().empty());
diff --git a/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc b/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc
index 6b370e6..c1eb2c6 100644
--- a/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc
+++ b/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc
@@ -14,6 +14,7 @@
 
 #include "gtest/gtest.h"
 #include "src/ast/type/f32_type.h"
+#include "src/ast/type/i32_type.h"
 #include "src/ast/type/multisampled_texture_type.h"
 #include "src/ast/type/sampled_texture_type.h"
 #include "src/ast/type/sampler_type.h"
@@ -90,7 +91,7 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->IsTexture());
   ASSERT_TRUE(t->AsTexture()->IsSampled());
-  ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsI32());
+  ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->Is<ast::type::I32Type>());
   EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d);
 }
 
@@ -170,7 +171,7 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->IsTexture());
   ASSERT_TRUE(t->AsTexture()->IsSampled());
-  ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsI32());
+  ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->Is<ast::type::I32Type>());
   EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d);
 }
 
@@ -236,7 +237,8 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->IsTexture());
   ASSERT_TRUE(t->AsTexture()->IsMultisampled());
-  ASSERT_TRUE(t->AsTexture()->AsMultisampled()->type()->IsI32());
+  ASSERT_TRUE(
+      t->AsTexture()->AsMultisampled()->type()->Is<ast::type::I32Type>());
   EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d);
 }
 
diff --git a/src/reader/wgsl/parser_impl_type_alias_test.cc b/src/reader/wgsl/parser_impl_type_alias_test.cc
index 45d02a3..12b5138 100644
--- a/src/reader/wgsl/parser_impl_type_alias_test.cc
+++ b/src/reader/wgsl/parser_impl_type_alias_test.cc
@@ -38,7 +38,7 @@
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::type::AliasType>());
   auto* alias = t->As<ast::type::AliasType>();
-  ASSERT_TRUE(alias->type()->IsI32());
+  ASSERT_TRUE(alias->type()->Is<ast::type::I32Type>());
   ASSERT_EQ(alias->type(), i32);
 }
 
diff --git a/src/reader/wgsl/parser_impl_type_decl_test.cc b/src/reader/wgsl/parser_impl_type_decl_test.cc
index 73fc77a..7d30582 100644
--- a/src/reader/wgsl/parser_impl_type_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_type_decl_test.cc
@@ -115,7 +115,7 @@
   EXPECT_FALSE(t.errored);
   ASSERT_NE(t.value, nullptr) << p->error();
   EXPECT_EQ(t.value, int_type);
-  ASSERT_TRUE(t->IsI32());
+  ASSERT_TRUE(t->Is<ast::type::I32Type>());
 }
 
 TEST_F(ParserImplTest, TypeDecl_U32) {
diff --git a/src/transform/bound_array_accessors_transform_test.cc b/src/transform/bound_array_accessors_transform_test.cc
index 6302423..664a519 100644
--- a/src/transform/bound_array_accessors_transform_test.cc
+++ b/src/transform/bound_array_accessors_transform_test.cc
@@ -375,7 +375,7 @@
   EXPECT_EQ(scalar->literal()->AsSint()->value(), 0);
 
   ASSERT_NE(ptr->idx_expr()->result_type(), nullptr);
-  ASSERT_TRUE(ptr->idx_expr()->result_type()->IsI32());
+  ASSERT_TRUE(ptr->idx_expr()->result_type()->Is<ast::type::I32Type>());
 }
 
 TEST_F(BoundArrayAccessorsTest, Array_Idx_OutOfBounds) {
@@ -553,7 +553,7 @@
   EXPECT_EQ(scalar->literal()->AsSint()->value(), 0);
 
   ASSERT_NE(ptr->idx_expr()->result_type(), nullptr);
-  ASSERT_TRUE(ptr->idx_expr()->result_type()->IsI32());
+  ASSERT_TRUE(ptr->idx_expr()->result_type()->Is<ast::type::I32Type>());
 }
 
 TEST_F(BoundArrayAccessorsTest, Vector_Idx_OutOfBounds) {
@@ -848,7 +848,7 @@
   EXPECT_EQ(scalar->literal()->AsSint()->value(), 0);
 
   ASSERT_NE(ary->idx_expr()->result_type(), nullptr);
-  ASSERT_TRUE(ary->idx_expr()->result_type()->IsI32());
+  ASSERT_TRUE(ary->idx_expr()->result_type()->Is<ast::type::I32Type>());
 
   ASSERT_TRUE(ptr->idx_expr()->IsConstructor());
   ASSERT_TRUE(ptr->idx_expr()->AsConstructor()->IsScalarConstructor());
@@ -858,7 +858,7 @@
   EXPECT_EQ(scalar->literal()->AsSint()->value(), 1);
 
   ASSERT_NE(ptr->idx_expr()->result_type(), nullptr);
-  ASSERT_TRUE(ptr->idx_expr()->result_type()->IsI32());
+  ASSERT_TRUE(ptr->idx_expr()->result_type()->Is<ast::type::I32Type>());
 }
 
 TEST_F(BoundArrayAccessorsTest, Matrix_Idx_Negative_Row) {
@@ -902,7 +902,7 @@
   EXPECT_EQ(scalar->literal()->AsSint()->value(), 2);
 
   ASSERT_NE(ary->idx_expr()->result_type(), nullptr);
-  ASSERT_TRUE(ary->idx_expr()->result_type()->IsI32());
+  ASSERT_TRUE(ary->idx_expr()->result_type()->Is<ast::type::I32Type>());
 
   ASSERT_TRUE(ptr->idx_expr()->IsConstructor());
   ASSERT_TRUE(ptr->idx_expr()->AsConstructor()->IsScalarConstructor());
@@ -912,7 +912,7 @@
   EXPECT_EQ(scalar->literal()->AsSint()->value(), 0);
 
   ASSERT_NE(ptr->idx_expr()->result_type(), nullptr);
-  ASSERT_TRUE(ptr->idx_expr()->result_type()->IsI32());
+  ASSERT_TRUE(ptr->idx_expr()->result_type()->Is<ast::type::I32Type>());
 }
 
 TEST_F(BoundArrayAccessorsTest, Matrix_Idx_OutOfBounds_Column) {
diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc
index 5ed83a1..f3c8735 100644
--- a/src/type_determiner_test.cc
+++ b/src/type_determiner_test.cc
@@ -135,7 +135,7 @@
   ASSERT_NE(lhs->result_type(), nullptr);
   ASSERT_NE(rhs->result_type(), nullptr);
 
-  EXPECT_TRUE(lhs->result_type()->IsI32());
+  EXPECT_TRUE(lhs->result_type()->Is<ast::type::I32Type>());
   EXPECT_TRUE(rhs->result_type()->Is<ast::type::F32Type>());
 }
 
@@ -158,7 +158,7 @@
   EXPECT_TRUE(td()->DetermineResultType(&cse));
   ASSERT_NE(lhs->result_type(), nullptr);
   ASSERT_NE(rhs->result_type(), nullptr);
-  EXPECT_TRUE(lhs->result_type()->IsI32());
+  EXPECT_TRUE(lhs->result_type()->Is<ast::type::I32Type>());
   EXPECT_TRUE(rhs->result_type()->Is<ast::type::F32Type>());
 }
 
@@ -177,7 +177,7 @@
   EXPECT_TRUE(td()->DetermineResultType(&block));
   ASSERT_NE(lhs->result_type(), nullptr);
   ASSERT_NE(rhs->result_type(), nullptr);
-  EXPECT_TRUE(lhs->result_type()->IsI32());
+  EXPECT_TRUE(lhs->result_type()->Is<ast::type::I32Type>());
   EXPECT_TRUE(rhs->result_type()->Is<ast::type::F32Type>());
 }
 
@@ -201,8 +201,8 @@
   ASSERT_NE(stmt.condition()->result_type(), nullptr);
   ASSERT_NE(lhs->result_type(), nullptr);
   ASSERT_NE(rhs->result_type(), nullptr);
-  EXPECT_TRUE(stmt.condition()->result_type()->IsI32());
-  EXPECT_TRUE(lhs->result_type()->IsI32());
+  EXPECT_TRUE(stmt.condition()->result_type()->Is<ast::type::I32Type>());
+  EXPECT_TRUE(lhs->result_type()->Is<ast::type::I32Type>());
   EXPECT_TRUE(rhs->result_type()->Is<ast::type::F32Type>());
 }
 
@@ -245,10 +245,10 @@
   ASSERT_NE(else_rhs->result_type(), nullptr);
   ASSERT_NE(lhs->result_type(), nullptr);
   ASSERT_NE(rhs->result_type(), nullptr);
-  EXPECT_TRUE(stmt.condition()->result_type()->IsI32());
-  EXPECT_TRUE(else_lhs->result_type()->IsI32());
+  EXPECT_TRUE(stmt.condition()->result_type()->Is<ast::type::I32Type>());
+  EXPECT_TRUE(else_lhs->result_type()->Is<ast::type::I32Type>());
   EXPECT_TRUE(else_rhs->result_type()->Is<ast::type::F32Type>());
-  EXPECT_TRUE(lhs->result_type()->IsI32());
+  EXPECT_TRUE(lhs->result_type()->Is<ast::type::I32Type>());
   EXPECT_TRUE(rhs->result_type()->Is<ast::type::F32Type>());
 }
 
@@ -280,9 +280,9 @@
   ASSERT_NE(body_rhs->result_type(), nullptr);
   ASSERT_NE(continuing_lhs->result_type(), nullptr);
   ASSERT_NE(continuing_rhs->result_type(), nullptr);
-  EXPECT_TRUE(body_lhs->result_type()->IsI32());
+  EXPECT_TRUE(body_lhs->result_type()->Is<ast::type::I32Type>());
   EXPECT_TRUE(body_rhs->result_type()->Is<ast::type::F32Type>());
-  EXPECT_TRUE(continuing_lhs->result_type()->IsI32());
+  EXPECT_TRUE(continuing_lhs->result_type()->Is<ast::type::I32Type>());
   EXPECT_TRUE(continuing_rhs->result_type()->Is<ast::type::F32Type>());
 }
 
@@ -296,7 +296,7 @@
 
   EXPECT_TRUE(td()->DetermineResultType(&ret));
   ASSERT_NE(cond->result_type(), nullptr);
-  EXPECT_TRUE(cond->result_type()->IsI32());
+  EXPECT_TRUE(cond->result_type()->Is<ast::type::I32Type>());
 }
 
 TEST_F(TypeDeterminerTest, Stmt_Return_WithoutValue) {
@@ -332,8 +332,8 @@
   ASSERT_NE(lhs->result_type(), nullptr);
   ASSERT_NE(rhs->result_type(), nullptr);
 
-  EXPECT_TRUE(stmt.condition()->result_type()->IsI32());
-  EXPECT_TRUE(lhs->result_type()->IsI32());
+  EXPECT_TRUE(stmt.condition()->result_type()->Is<ast::type::I32Type>());
+  EXPECT_TRUE(lhs->result_type()->Is<ast::type::I32Type>());
   EXPECT_TRUE(rhs->result_type()->Is<ast::type::F32Type>());
 }
 
@@ -395,7 +395,7 @@
 
   EXPECT_TRUE(td()->DetermineResultType(&decl));
   ASSERT_NE(init->result_type(), nullptr);
-  EXPECT_TRUE(init->result_type()->IsI32());
+  EXPECT_TRUE(init->result_type()->Is<ast::type::I32Type>());
 }
 
 TEST_F(TypeDeterminerTest, Stmt_VariableDecl_ModuleScope) {
@@ -409,7 +409,7 @@
 
   EXPECT_TRUE(td()->Determine());
   ASSERT_NE(init->result_type(), nullptr);
-  EXPECT_TRUE(init->result_type()->IsI32());
+  EXPECT_TRUE(init->result_type()->Is<ast::type::I32Type>());
 }
 
 TEST_F(TypeDeterminerTest, Expr_Error_Unknown) {
@@ -1140,7 +1140,7 @@
 
   ASSERT_TRUE(td()->DetermineResultType(&expr)) << td()->error();
   ASSERT_NE(expr.result_type(), nullptr);
-  EXPECT_TRUE(expr.result_type()->IsI32());
+  EXPECT_TRUE(expr.result_type()->Is<ast::type::I32Type>());
 }
 
 TEST_P(Expr_Binary_BitwiseTest, Vector) {
@@ -1161,7 +1161,7 @@
   ASSERT_TRUE(td()->DetermineResultType(&expr)) << td()->error();
   ASSERT_NE(expr.result_type(), nullptr);
   ASSERT_TRUE(expr.result_type()->IsVector());
-  EXPECT_TRUE(expr.result_type()->AsVector()->type()->IsI32());
+  EXPECT_TRUE(expr.result_type()->AsVector()->type()->Is<ast::type::I32Type>());
   EXPECT_EQ(expr.result_type()->AsVector()->size(), 3u);
 }
 INSTANTIATE_TEST_SUITE_P(TypeDeterminerTest,
@@ -1290,7 +1290,7 @@
 
   ASSERT_TRUE(td()->DetermineResultType(&expr)) << td()->error();
   ASSERT_NE(expr.result_type(), nullptr);
-  EXPECT_TRUE(expr.result_type()->IsI32());
+  EXPECT_TRUE(expr.result_type()->Is<ast::type::I32Type>());
 }
 
 TEST_F(TypeDeterminerTest, Expr_Binary_Multiply_Vector_Scalar) {
@@ -1748,7 +1748,7 @@
       ast::type::TextureDimension dim,
       ast::type::Type* type) {
     if (dim == ast::type::TextureDimension::k1d) {
-      if (type->IsI32()) {
+      if (type->Is<ast::type::I32Type>()) {
         return std::make_unique<ast::type::I32Type>();
       } else if (type->IsU32()) {
         return std::make_unique<ast::type::U32Type>();
@@ -1814,7 +1814,8 @@
     EXPECT_TRUE(
         expr.result_type()->AsVector()->type()->Is<ast::type::F32Type>());
   } else if (type == TextureType::kI32) {
-    EXPECT_TRUE(expr.result_type()->AsVector()->type()->IsI32());
+    EXPECT_TRUE(
+        expr.result_type()->AsVector()->type()->Is<ast::type::I32Type>());
   } else {
     EXPECT_TRUE(expr.result_type()->AsVector()->type()->IsU32());
   }
@@ -1885,7 +1886,8 @@
     EXPECT_TRUE(
         expr.result_type()->AsVector()->type()->Is<ast::type::F32Type>());
   } else if (type == TextureType::kI32) {
-    EXPECT_TRUE(expr.result_type()->AsVector()->type()->IsI32());
+    EXPECT_TRUE(
+        expr.result_type()->AsVector()->type()->Is<ast::type::I32Type>());
   } else {
     EXPECT_TRUE(expr.result_type()->AsVector()->type()->IsU32());
   }
@@ -2426,7 +2428,7 @@
 
   EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
   ASSERT_NE(ident->result_type(), nullptr);
-  EXPECT_TRUE(ident->result_type()->IsI32());
+  EXPECT_TRUE(ident->result_type()->Is<ast::type::I32Type>());
 }
 
 TEST_P(ImportData_SingleParam_FloatOrInt_Test, Sint_Vector) {
@@ -3488,7 +3490,7 @@
 
   EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
   ASSERT_NE(ident->result_type(), nullptr);
-  EXPECT_TRUE(ident->result_type()->IsI32());
+  EXPECT_TRUE(ident->result_type()->Is<ast::type::I32Type>());
 }
 
 TEST_P(ImportData_ThreeParam_FloatOrInt_Test, Sint_Vector) {
@@ -3894,7 +3896,7 @@
 
   EXPECT_TRUE(td()->DetermineResultType(&call)) << td()->error();
   ASSERT_NE(ident->result_type(), nullptr);
-  EXPECT_TRUE(ident->result_type()->IsI32());
+  EXPECT_TRUE(ident->result_type()->Is<ast::type::I32Type>());
 }
 
 TEST_P(ImportData_FloatOrInt_TwoParamTest, Scalar_Unsigned) {
diff --git a/src/validator/validator_impl.cc b/src/validator/validator_impl.cc
index f53931b..a9d1000 100644
--- a/src/validator/validator_impl.cc
+++ b/src/validator/validator_impl.cc
@@ -316,7 +316,7 @@
   }
 
   auto* cond_type = s->condition()->result_type()->UnwrapAll();
-  if (!(cond_type->IsI32() || cond_type->IsU32())) {
+  if (!(cond_type->Is<ast::type::I32Type>() || cond_type->IsU32())) {
     add_error(s->condition()->source(), "v-0025",
               "switch statement selector expression must be of a "
               "scalar integer type");
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index 5528b3f..e1db5d0 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -265,8 +265,8 @@
 bool GeneratorImpl::EmitBitcast(std::ostream& pre,
                                 std::ostream& out,
                                 ast::BitcastExpression* expr) {
-  if (!expr->type()->Is<ast::type::F32Type>() && !expr->type()->IsI32() &&
-      !expr->type()->IsU32()) {
+  if (!expr->type()->Is<ast::type::F32Type>() &&
+      !expr->type()->Is<ast::type::I32Type>() && !expr->type()->IsU32()) {
     error_ = "Unable to do bitcast to type " + expr->type()->type_name();
     return false;
   }
@@ -1547,7 +1547,7 @@
     out << "false";
   } else if (type->Is<ast::type::F32Type>()) {
     out << "0.0f";
-  } else if (type->IsI32()) {
+  } else if (type->Is<ast::type::I32Type>()) {
     out << "0";
   } else if (type->IsU32()) {
     out << "0u";
@@ -2062,7 +2062,7 @@
     out << "bool";
   } else if (type->Is<ast::type::F32Type>()) {
     out << "float";
-  } else if (type->IsI32()) {
+  } else if (type->Is<ast::type::I32Type>()) {
     out << "int";
   } else if (type->IsMatrix()) {
     auto* mat = type->AsMatrix();
@@ -2125,7 +2125,8 @@
     auto size = vec->size();
     if (vec->type()->Is<ast::type::F32Type>() && size >= 1 && size <= 4) {
       out << "float" << size;
-    } else if (vec->type()->IsI32() && size >= 1 && size <= 4) {
+    } else if (vec->type()->Is<ast::type::I32Type>() && size >= 1 &&
+               size <= 4) {
       out << "int" << size;
     } else if (vec->type()->IsU32() && size >= 1 && size <= 4) {
       out << "uint" << size;
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index d1d5fa4..8d85591 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -200,7 +200,8 @@
   if (type->IsPointer()) {
     return 0;
   }
-  if (type->Is<ast::type::F32Type>() || type->IsI32() || type->IsU32()) {
+  if (type->Is<ast::type::F32Type>() || type->Is<ast::type::I32Type>() ||
+      type->IsU32()) {
     return 4;
   }
   if (type->IsMatrix()) {
@@ -796,7 +797,7 @@
       if (ident->result_type()->Is<ast::type::F32Type>()) {
         out += "fabs";
       } else if (ident->result_type()->IsU32() ||
-                 ident->result_type()->IsI32()) {
+                 ident->result_type()->Is<ast::type::I32Type>()) {
         out += "abs";
       }
       break;
@@ -804,7 +805,7 @@
       if (ident->result_type()->Is<ast::type::F32Type>()) {
         out += "fmax";
       } else if (ident->result_type()->IsU32() ||
-                 ident->result_type()->IsI32()) {
+                 ident->result_type()->Is<ast::type::I32Type>()) {
         out += "max";
       }
       break;
@@ -812,7 +813,7 @@
       if (ident->result_type()->Is<ast::type::F32Type>()) {
         out += "fmin";
       } else if (ident->result_type()->IsU32() ||
-                 ident->result_type()->IsI32()) {
+                 ident->result_type()->Is<ast::type::I32Type>()) {
         out += "min";
       }
       break;
@@ -932,7 +933,7 @@
     out_ << "false";
   } else if (type->Is<ast::type::F32Type>()) {
     out_ << "0.0f";
-  } else if (type->IsI32()) {
+  } else if (type->Is<ast::type::I32Type>()) {
     out_ << "0";
   } else if (type->IsU32()) {
     out_ << "0u";
@@ -1816,7 +1817,7 @@
     out_ << "bool";
   } else if (type->Is<ast::type::F32Type>()) {
     out_ << "float";
-  } else if (type->IsI32()) {
+  } else if (type->Is<ast::type::I32Type>()) {
     out_ << "int";
   } else if (type->IsMatrix()) {
     auto* mat = type->AsMatrix();
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index d447be4..e7efa82 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -748,7 +748,7 @@
       } else if (type->IsU32()) {
         ast::UintLiteral l(type, 0);
         init_id = GenerateLiteralIfNeeded(var, &l);
-      } else if (type->IsI32()) {
+      } else if (type->Is<ast::type::I32Type>()) {
         ast::SintLiteral l(type, 0);
         init_id = GenerateLiteralIfNeeded(var, &l);
       } else if (type->Is<ast::type::BoolType>()) {
@@ -1393,14 +1393,16 @@
   auto* from_type = from_expr->result_type()->UnwrapPtrIfNeeded();
 
   spv::Op op = spv::Op::OpNop;
-  if ((from_type->IsI32() && to_type->Is<ast::type::F32Type>()) ||
+  if ((from_type->Is<ast::type::I32Type>() &&
+       to_type->Is<ast::type::F32Type>()) ||
       (from_type->is_signed_integer_vector() && to_type->is_float_vector())) {
     op = spv::Op::OpConvertSToF;
   } else if ((from_type->IsU32() && to_type->Is<ast::type::F32Type>()) ||
              (from_type->is_unsigned_integer_vector() &&
               to_type->is_float_vector())) {
     op = spv::Op::OpConvertUToF;
-  } else if ((from_type->Is<ast::type::F32Type>() && to_type->IsI32()) ||
+  } else if ((from_type->Is<ast::type::F32Type>() &&
+              to_type->Is<ast::type::I32Type>()) ||
              (from_type->is_float_vector() &&
               to_type->is_signed_integer_vector())) {
     op = spv::Op::OpConvertFToS;
@@ -1411,13 +1413,14 @@
   } else if ((from_type->Is<ast::type::BoolType>() &&
               to_type->Is<ast::type::BoolType>()) ||
              (from_type->IsU32() && to_type->IsU32()) ||
-             (from_type->IsI32() && to_type->IsI32()) ||
+             (from_type->Is<ast::type::I32Type>() &&
+              to_type->Is<ast::type::I32Type>()) ||
              (from_type->Is<ast::type::F32Type>() &&
               to_type->Is<ast::type::F32Type>()) ||
              (from_type->IsVector() && (from_type == to_type))) {
     return val_id;
-  } else if ((from_type->IsI32() && to_type->IsU32()) ||
-             (from_type->IsU32() && to_type->IsI32()) ||
+  } else if ((from_type->Is<ast::type::I32Type>() && to_type->IsU32()) ||
+             (from_type->IsU32() && to_type->Is<ast::type::I32Type>()) ||
              (from_type->is_signed_integer_vector() &&
               to_type->is_unsigned_integer_vector()) ||
              (from_type->is_unsigned_integer_vector() &&
@@ -2421,7 +2424,7 @@
     push_type(spv::Op::OpTypeBool, {result});
   } else if (type->Is<ast::type::F32Type>()) {
     push_type(spv::Op::OpTypeFloat, {result, Operand::Int(32)});
-  } else if (type->IsI32()) {
+  } 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)) {
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc
index 706c9f0..e7a65e8 100644
--- a/src/writer/wgsl/generator_impl.cc
+++ b/src/writer/wgsl/generator_impl.cc
@@ -54,8 +54,9 @@
 #include "src/ast/type/access_control_type.h"
 #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/depth_texture_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/multisampled_texture_type.h"
 #include "src/ast/type/pointer_type.h"
@@ -436,7 +437,7 @@
     out_ << "bool";
   } else if (type->Is<ast::type::F32Type>()) {
     out_ << "f32";
-  } else if (type->IsI32()) {
+  } else if (type->Is<ast::type::I32Type>()) {
     out_ << "i32";
   } else if (type->IsMatrix()) {
     auto* mat = type->AsMatrix();