From a8d87788da503ca00de684435585dcc80e005dfb Mon Sep 17 00:00:00 2001
From: Ben Clayton <bclayton@google.com>
Date: Mon, 30 Nov 2020 23:30:58 +0000
Subject: [PATCH] Replace Type::(Is|As)AccessControl with Castable

Change-Id: I833c92be270236fefd1e77a7a145dede757e93e9
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/34262
Reviewed-by: dan sinclair <dsinclair@chromium.org>
---
 src/ast/type/access_control_type.cc           |  6 +---
 src/ast/type/access_control_type.h            |  3 --
 src/ast/type/access_control_type_test.cc      |  2 +-
 src/ast/type/alias_type_test.cc               | 27 ++++++++---------
 src/ast/type/array_type_test.cc               | 28 +++++++++---------
 src/ast/type/bool_type_test.cc                | 28 +++++++++---------
 src/ast/type/depth_texture_type_test.cc       | 29 ++++++++++---------
 src/ast/type/f32_type_test.cc                 | 28 +++++++++---------
 src/ast/type/i32_type_test.cc                 | 28 +++++++++---------
 src/ast/type/matrix_type_test.cc              | 28 +++++++++---------
 .../type/multisampled_texture_type_test.cc    | 28 +++++++++---------
 src/ast/type/pointer_type_test.cc             | 28 +++++++++---------
 src/ast/type/sampled_texture_type_test.cc     | 28 +++++++++---------
 src/ast/type/sampler_type_test.cc             | 28 +++++++++---------
 src/ast/type/storage_texture_type_test.cc     | 28 +++++++++---------
 src/ast/type/struct_type_test.cc              | 28 +++++++++---------
 src/ast/type/type.cc                          | 22 +++-----------
 src/ast/type/type.h                           |  7 -----
 src/ast/type/u32_type_test.cc                 | 28 +++++++++---------
 src/ast/type/vector_type_test.cc              | 28 +++++++++---------
 src/inspector/inspector.cc                    |  6 ++--
 .../parser_impl_variable_ident_decl_test.cc   |  8 ++---
 src/writer/hlsl/generator_impl.cc             |  4 +--
 src/writer/msl/generator_impl.cc              |  8 ++---
 src/writer/spirv/builder.cc                   |  4 +--
 src/writer/wgsl/generator_impl.cc             |  4 +--
 26 files changed, 248 insertions(+), 246 deletions(-)

diff --git a/src/ast/type/access_control_type.cc b/src/ast/type/access_control_type.cc
index 8b3399183a..4e59370287 100644
--- a/src/ast/type/access_control_type.cc
+++ b/src/ast/type/access_control_type.cc
@@ -23,17 +23,13 @@ namespace type {
 AccessControlType::AccessControlType(AccessControl access, Type* subtype)
     : access_(access), subtype_(subtype) {
   assert(subtype_);
-  assert(!subtype_->IsAccessControl());
+  assert(!subtype_->Is<AccessControlType>());
 }
 
 AccessControlType::AccessControlType(AccessControlType&&) = default;
 
 AccessControlType::~AccessControlType() = default;
 
-bool AccessControlType::IsAccessControl() const {
-  return true;
-}
-
 std::string AccessControlType::type_name() const {
   std::string name = "__access_control_";
   switch (access_) {
diff --git a/src/ast/type/access_control_type.h b/src/ast/type/access_control_type.h
index 4b5071d144..9e31d67a35 100644
--- a/src/ast/type/access_control_type.h
+++ b/src/ast/type/access_control_type.h
@@ -35,9 +35,6 @@ class AccessControlType : public Castable<AccessControlType, Type> {
   AccessControlType(AccessControlType&&);
   ~AccessControlType() override;
 
-  /// @returns true if the type is an access control type
-  bool IsAccessControl() const override;
-
   /// @returns true if the access control is read only
   bool IsReadOnly() const { return access_ == AccessControl::kReadOnly; }
   /// @returns true if the access control is write only
diff --git a/src/ast/type/access_control_type_test.cc b/src/ast/type/access_control_type_test.cc
index ba63f63edb..afa2463eac 100644
--- a/src/ast/type/access_control_type_test.cc
+++ b/src/ast/type/access_control_type_test.cc
@@ -47,7 +47,7 @@ TEST_F(AccessControlTypeTest, Is) {
   I32Type i32;
 
   AccessControlType at{AccessControl::kReadOnly, &i32};
-  EXPECT_TRUE(at.IsAccessControl());
+  EXPECT_TRUE(at.Is<AccessControlType>());
   EXPECT_FALSE(at.IsAlias());
   EXPECT_FALSE(at.IsArray());
   EXPECT_FALSE(at.IsBool());
diff --git a/src/ast/type/alias_type_test.cc b/src/ast/type/alias_type_test.cc
index 729a12bbec..9c2137a775 100644
--- a/src/ast/type/alias_type_test.cc
+++ b/src/ast/type/alias_type_test.cc
@@ -48,19 +48,20 @@ TEST_F(AliasTypeTest, Is) {
   I32Type i32;
 
   AliasType at{"a", &i32};
-  EXPECT_FALSE(at.IsAccessControl());
-  EXPECT_TRUE(at.IsAlias());
-  EXPECT_FALSE(at.IsArray());
-  EXPECT_FALSE(at.IsBool());
-  EXPECT_FALSE(at.IsF32());
-  EXPECT_FALSE(at.IsI32());
-  EXPECT_FALSE(at.IsMatrix());
-  EXPECT_FALSE(at.IsPointer());
-  EXPECT_FALSE(at.IsSampler());
-  EXPECT_FALSE(at.IsStruct());
-  EXPECT_FALSE(at.IsTexture());
-  EXPECT_FALSE(at.IsU32());
-  EXPECT_FALSE(at.IsVector());
+  Type* ty = &at;
+  EXPECT_FALSE(ty->Is<AccessControlType>());
+  EXPECT_TRUE(ty->IsAlias());
+  EXPECT_FALSE(ty->IsArray());
+  EXPECT_FALSE(ty->IsBool());
+  EXPECT_FALSE(ty->IsF32());
+  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->IsPointer());
+  EXPECT_FALSE(ty->IsSampler());
+  EXPECT_FALSE(ty->IsStruct());
+  EXPECT_FALSE(ty->IsTexture());
+  EXPECT_FALSE(ty->IsU32());
+  EXPECT_FALSE(ty->IsVector());
 }
 
 TEST_F(AliasTypeTest, TypeName) {
diff --git a/src/ast/type/array_type_test.cc b/src/ast/type/array_type_test.cc
index 447d6b8354..04267d3719 100644
--- a/src/ast/type/array_type_test.cc
+++ b/src/ast/type/array_type_test.cc
@@ -19,6 +19,7 @@
 
 #include "src/ast/stride_decoration.h"
 #include "src/ast/test_helper.h"
+#include "src/ast/type/access_control_type.h"
 #include "src/ast/type/i32_type.h"
 #include "src/ast/type/u32_type.h"
 
@@ -51,19 +52,20 @@ TEST_F(ArrayTypeTest, Is) {
   I32Type i32;
 
   ArrayType arr{&i32, 3};
-  EXPECT_FALSE(arr.IsAccessControl());
-  EXPECT_FALSE(arr.IsAlias());
-  EXPECT_TRUE(arr.IsArray());
-  EXPECT_FALSE(arr.IsBool());
-  EXPECT_FALSE(arr.IsF32());
-  EXPECT_FALSE(arr.IsI32());
-  EXPECT_FALSE(arr.IsMatrix());
-  EXPECT_FALSE(arr.IsPointer());
-  EXPECT_FALSE(arr.IsSampler());
-  EXPECT_FALSE(arr.IsStruct());
-  EXPECT_FALSE(arr.IsTexture());
-  EXPECT_FALSE(arr.IsU32());
-  EXPECT_FALSE(arr.IsVector());
+  Type* ty = &arr;
+  EXPECT_FALSE(ty->Is<AccessControlType>());
+  EXPECT_FALSE(ty->IsAlias());
+  EXPECT_TRUE(ty->IsArray());
+  EXPECT_FALSE(ty->IsBool());
+  EXPECT_FALSE(ty->IsF32());
+  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->IsPointer());
+  EXPECT_FALSE(ty->IsSampler());
+  EXPECT_FALSE(ty->IsStruct());
+  EXPECT_FALSE(ty->IsTexture());
+  EXPECT_FALSE(ty->IsU32());
+  EXPECT_FALSE(ty->IsVector());
 }
 
 TEST_F(ArrayTypeTest, TypeName) {
diff --git a/src/ast/type/bool_type_test.cc b/src/ast/type/bool_type_test.cc
index 50b7aa2453..9efe20c3d0 100644
--- a/src/ast/type/bool_type_test.cc
+++ b/src/ast/type/bool_type_test.cc
@@ -15,6 +15,7 @@
 #include "src/ast/type/bool_type.h"
 
 #include "src/ast/test_helper.h"
+#include "src/ast/type/access_control_type.h"
 
 namespace tint {
 namespace ast {
@@ -25,19 +26,20 @@ using BoolTypeTest = TestHelper;
 
 TEST_F(BoolTypeTest, Is) {
   BoolType b;
-  EXPECT_FALSE(b.IsAccessControl());
-  EXPECT_FALSE(b.IsAlias());
-  EXPECT_FALSE(b.IsArray());
-  EXPECT_TRUE(b.IsBool());
-  EXPECT_FALSE(b.IsF32());
-  EXPECT_FALSE(b.IsI32());
-  EXPECT_FALSE(b.IsMatrix());
-  EXPECT_FALSE(b.IsPointer());
-  EXPECT_FALSE(b.IsSampler());
-  EXPECT_FALSE(b.IsStruct());
-  EXPECT_FALSE(b.IsTexture());
-  EXPECT_FALSE(b.IsU32());
-  EXPECT_FALSE(b.IsVector());
+  Type* ty = &b;
+  EXPECT_FALSE(ty->Is<AccessControlType>());
+  EXPECT_FALSE(ty->IsAlias());
+  EXPECT_FALSE(ty->IsArray());
+  EXPECT_TRUE(ty->IsBool());
+  EXPECT_FALSE(ty->IsF32());
+  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->IsPointer());
+  EXPECT_FALSE(ty->IsSampler());
+  EXPECT_FALSE(ty->IsStruct());
+  EXPECT_FALSE(ty->IsTexture());
+  EXPECT_FALSE(ty->IsU32());
+  EXPECT_FALSE(ty->IsVector());
 }
 
 TEST_F(BoolTypeTest, TypeName) {
diff --git a/src/ast/type/depth_texture_type_test.cc b/src/ast/type/depth_texture_type_test.cc
index 554e906a28..852dc62916 100644
--- a/src/ast/type/depth_texture_type_test.cc
+++ b/src/ast/type/depth_texture_type_test.cc
@@ -16,6 +16,8 @@
 
 #include "src/ast/test_helper.h"
 
+#include "src/ast/type/access_control_type.h"
+
 namespace tint {
 namespace ast {
 namespace type {
@@ -25,19 +27,20 @@ using DepthTextureTypeTest = TestHelper;
 
 TEST_F(DepthTextureTypeTest, Is) {
   DepthTextureType d(TextureDimension::kCube);
-  EXPECT_FALSE(d.IsAccessControl());
-  EXPECT_FALSE(d.IsAlias());
-  EXPECT_FALSE(d.IsArray());
-  EXPECT_FALSE(d.IsBool());
-  EXPECT_FALSE(d.IsF32());
-  EXPECT_FALSE(d.IsI32());
-  EXPECT_FALSE(d.IsMatrix());
-  EXPECT_FALSE(d.IsPointer());
-  EXPECT_FALSE(d.IsSampler());
-  EXPECT_FALSE(d.IsStruct());
-  EXPECT_TRUE(d.IsTexture());
-  EXPECT_FALSE(d.IsU32());
-  EXPECT_FALSE(d.IsVector());
+  Type* ty = &d;
+  EXPECT_FALSE(ty->Is<AccessControlType>());
+  EXPECT_FALSE(ty->IsAlias());
+  EXPECT_FALSE(ty->IsArray());
+  EXPECT_FALSE(ty->IsBool());
+  EXPECT_FALSE(ty->IsF32());
+  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->IsPointer());
+  EXPECT_FALSE(ty->IsSampler());
+  EXPECT_FALSE(ty->IsStruct());
+  EXPECT_TRUE(ty->IsTexture());
+  EXPECT_FALSE(ty->IsU32());
+  EXPECT_FALSE(ty->IsVector());
 }
 
 TEST_F(DepthTextureTypeTest, IsTextureType) {
diff --git a/src/ast/type/f32_type_test.cc b/src/ast/type/f32_type_test.cc
index c6978d5ff0..3267400b63 100644
--- a/src/ast/type/f32_type_test.cc
+++ b/src/ast/type/f32_type_test.cc
@@ -15,6 +15,7 @@
 #include "src/ast/type/f32_type.h"
 
 #include "src/ast/test_helper.h"
+#include "src/ast/type/access_control_type.h"
 
 namespace tint {
 namespace ast {
@@ -25,19 +26,20 @@ using F32TypeTest = TestHelper;
 
 TEST_F(F32TypeTest, Is) {
   F32Type f;
-  EXPECT_FALSE(f.IsAccessControl());
-  EXPECT_FALSE(f.IsAlias());
-  EXPECT_FALSE(f.IsArray());
-  EXPECT_FALSE(f.IsBool());
-  EXPECT_TRUE(f.IsF32());
-  EXPECT_FALSE(f.IsI32());
-  EXPECT_FALSE(f.IsMatrix());
-  EXPECT_FALSE(f.IsPointer());
-  EXPECT_FALSE(f.IsSampler());
-  EXPECT_FALSE(f.IsStruct());
-  EXPECT_FALSE(f.IsTexture());
-  EXPECT_FALSE(f.IsU32());
-  EXPECT_FALSE(f.IsVector());
+  Type* ty = &f;
+  EXPECT_FALSE(ty->Is<AccessControlType>());
+  EXPECT_FALSE(ty->IsAlias());
+  EXPECT_FALSE(ty->IsArray());
+  EXPECT_FALSE(ty->IsBool());
+  EXPECT_TRUE(ty->IsF32());
+  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->IsPointer());
+  EXPECT_FALSE(ty->IsSampler());
+  EXPECT_FALSE(ty->IsStruct());
+  EXPECT_FALSE(ty->IsTexture());
+  EXPECT_FALSE(ty->IsU32());
+  EXPECT_FALSE(ty->IsVector());
 }
 
 TEST_F(F32TypeTest, TypeName) {
diff --git a/src/ast/type/i32_type_test.cc b/src/ast/type/i32_type_test.cc
index 6f9538dc45..d0d3e25b9b 100644
--- a/src/ast/type/i32_type_test.cc
+++ b/src/ast/type/i32_type_test.cc
@@ -15,6 +15,7 @@
 #include "src/ast/type/i32_type.h"
 
 #include "src/ast/test_helper.h"
+#include "src/ast/type/access_control_type.h"
 
 namespace tint {
 namespace ast {
@@ -25,19 +26,20 @@ using I32TypeTest = TestHelper;
 
 TEST_F(I32TypeTest, Is) {
   I32Type i;
-  EXPECT_FALSE(i.IsAccessControl());
-  EXPECT_FALSE(i.IsAlias());
-  EXPECT_FALSE(i.IsArray());
-  EXPECT_FALSE(i.IsBool());
-  EXPECT_FALSE(i.IsF32());
-  EXPECT_TRUE(i.IsI32());
-  EXPECT_FALSE(i.IsMatrix());
-  EXPECT_FALSE(i.IsPointer());
-  EXPECT_FALSE(i.IsSampler());
-  EXPECT_FALSE(i.IsStruct());
-  EXPECT_FALSE(i.IsTexture());
-  EXPECT_FALSE(i.IsU32());
-  EXPECT_FALSE(i.IsVector());
+  Type* ty = &i;
+  EXPECT_FALSE(ty->Is<AccessControlType>());
+  EXPECT_FALSE(ty->IsAlias());
+  EXPECT_FALSE(ty->IsArray());
+  EXPECT_FALSE(ty->IsBool());
+  EXPECT_FALSE(ty->IsF32());
+  EXPECT_TRUE(ty->IsI32());
+  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->IsPointer());
+  EXPECT_FALSE(ty->IsSampler());
+  EXPECT_FALSE(ty->IsStruct());
+  EXPECT_FALSE(ty->IsTexture());
+  EXPECT_FALSE(ty->IsU32());
+  EXPECT_FALSE(ty->IsVector());
 }
 
 TEST_F(I32TypeTest, TypeName) {
diff --git a/src/ast/type/matrix_type_test.cc b/src/ast/type/matrix_type_test.cc
index c59a3c01d0..068aeed949 100644
--- a/src/ast/type/matrix_type_test.cc
+++ b/src/ast/type/matrix_type_test.cc
@@ -15,6 +15,7 @@
 #include "src/ast/type/matrix_type.h"
 
 #include "src/ast/test_helper.h"
+#include "src/ast/type/access_control_type.h"
 #include "src/ast/type/i32_type.h"
 
 namespace tint {
@@ -35,19 +36,20 @@ TEST_F(MatrixTypeTest, Creation) {
 TEST_F(MatrixTypeTest, Is) {
   I32Type i32;
   MatrixType m{&i32, 2, 3};
-  EXPECT_FALSE(m.IsAccessControl());
-  EXPECT_FALSE(m.IsAlias());
-  EXPECT_FALSE(m.IsArray());
-  EXPECT_FALSE(m.IsBool());
-  EXPECT_FALSE(m.IsF32());
-  EXPECT_FALSE(m.IsI32());
-  EXPECT_TRUE(m.IsMatrix());
-  EXPECT_FALSE(m.IsPointer());
-  EXPECT_FALSE(m.IsSampler());
-  EXPECT_FALSE(m.IsStruct());
-  EXPECT_FALSE(m.IsTexture());
-  EXPECT_FALSE(m.IsU32());
-  EXPECT_FALSE(m.IsVector());
+  Type* ty = &m;
+  EXPECT_FALSE(ty->Is<AccessControlType>());
+  EXPECT_FALSE(ty->IsAlias());
+  EXPECT_FALSE(ty->IsArray());
+  EXPECT_FALSE(ty->IsBool());
+  EXPECT_FALSE(ty->IsF32());
+  EXPECT_FALSE(ty->IsI32());
+  EXPECT_TRUE(ty->IsMatrix());
+  EXPECT_FALSE(ty->IsPointer());
+  EXPECT_FALSE(ty->IsSampler());
+  EXPECT_FALSE(ty->IsStruct());
+  EXPECT_FALSE(ty->IsTexture());
+  EXPECT_FALSE(ty->IsU32());
+  EXPECT_FALSE(ty->IsVector());
 }
 
 TEST_F(MatrixTypeTest, TypeName) {
diff --git a/src/ast/type/multisampled_texture_type_test.cc b/src/ast/type/multisampled_texture_type_test.cc
index 911c1a2f2f..8c89c9a427 100644
--- a/src/ast/type/multisampled_texture_type_test.cc
+++ b/src/ast/type/multisampled_texture_type_test.cc
@@ -15,6 +15,7 @@
 #include "src/ast/type/multisampled_texture_type.h"
 
 #include "src/ast/test_helper.h"
+#include "src/ast/type/access_control_type.h"
 #include "src/ast/type/f32_type.h"
 
 namespace tint {
@@ -27,19 +28,20 @@ using MultisampledTextureTypeTest = TestHelper;
 TEST_F(MultisampledTextureTypeTest, Is) {
   F32Type f32;
   MultisampledTextureType s(TextureDimension::kCube, &f32);
-  EXPECT_FALSE(s.IsAccessControl());
-  EXPECT_FALSE(s.IsAlias());
-  EXPECT_FALSE(s.IsArray());
-  EXPECT_FALSE(s.IsBool());
-  EXPECT_FALSE(s.IsF32());
-  EXPECT_FALSE(s.IsI32());
-  EXPECT_FALSE(s.IsMatrix());
-  EXPECT_FALSE(s.IsPointer());
-  EXPECT_FALSE(s.IsSampler());
-  EXPECT_FALSE(s.IsStruct());
-  EXPECT_TRUE(s.IsTexture());
-  EXPECT_FALSE(s.IsU32());
-  EXPECT_FALSE(s.IsVector());
+  Type* ty = &s;
+  EXPECT_FALSE(ty->Is<AccessControlType>());
+  EXPECT_FALSE(ty->IsAlias());
+  EXPECT_FALSE(ty->IsArray());
+  EXPECT_FALSE(ty->IsBool());
+  EXPECT_FALSE(ty->IsF32());
+  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->IsPointer());
+  EXPECT_FALSE(ty->IsSampler());
+  EXPECT_FALSE(ty->IsStruct());
+  EXPECT_TRUE(ty->IsTexture());
+  EXPECT_FALSE(ty->IsU32());
+  EXPECT_FALSE(ty->IsVector());
 }
 
 TEST_F(MultisampledTextureTypeTest, IsTextureType) {
diff --git a/src/ast/type/pointer_type_test.cc b/src/ast/type/pointer_type_test.cc
index 5d7c1ec6b7..9d3764d55c 100644
--- a/src/ast/type/pointer_type_test.cc
+++ b/src/ast/type/pointer_type_test.cc
@@ -15,6 +15,7 @@
 #include "src/ast/type/pointer_type.h"
 
 #include "src/ast/test_helper.h"
+#include "src/ast/type/access_control_type.h"
 #include "src/ast/type/i32_type.h"
 
 namespace tint {
@@ -34,19 +35,20 @@ TEST_F(PointerTypeTest, Creation) {
 TEST_F(PointerTypeTest, Is) {
   I32Type i32;
   PointerType p{&i32, StorageClass::kFunction};
-  EXPECT_FALSE(p.IsAccessControl());
-  EXPECT_FALSE(p.IsAlias());
-  EXPECT_FALSE(p.IsArray());
-  EXPECT_FALSE(p.IsBool());
-  EXPECT_FALSE(p.IsF32());
-  EXPECT_FALSE(p.IsI32());
-  EXPECT_FALSE(p.IsMatrix());
-  EXPECT_TRUE(p.IsPointer());
-  EXPECT_FALSE(p.IsSampler());
-  EXPECT_FALSE(p.IsStruct());
-  EXPECT_FALSE(p.IsTexture());
-  EXPECT_FALSE(p.IsU32());
-  EXPECT_FALSE(p.IsVector());
+  Type* ty = &p;
+  EXPECT_FALSE(ty->Is<AccessControlType>());
+  EXPECT_FALSE(ty->IsAlias());
+  EXPECT_FALSE(ty->IsArray());
+  EXPECT_FALSE(ty->IsBool());
+  EXPECT_FALSE(ty->IsF32());
+  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_TRUE(ty->IsPointer());
+  EXPECT_FALSE(ty->IsSampler());
+  EXPECT_FALSE(ty->IsStruct());
+  EXPECT_FALSE(ty->IsTexture());
+  EXPECT_FALSE(ty->IsU32());
+  EXPECT_FALSE(ty->IsVector());
 }
 
 TEST_F(PointerTypeTest, TypeName) {
diff --git a/src/ast/type/sampled_texture_type_test.cc b/src/ast/type/sampled_texture_type_test.cc
index 359fa33a38..d709928399 100644
--- a/src/ast/type/sampled_texture_type_test.cc
+++ b/src/ast/type/sampled_texture_type_test.cc
@@ -15,6 +15,7 @@
 #include "src/ast/type/sampled_texture_type.h"
 
 #include "src/ast/test_helper.h"
+#include "src/ast/type/access_control_type.h"
 #include "src/ast/type/f32_type.h"
 
 namespace tint {
@@ -27,19 +28,20 @@ using SampledTextureTypeTest = TestHelper;
 TEST_F(SampledTextureTypeTest, Is) {
   F32Type f32;
   SampledTextureType s(TextureDimension::kCube, &f32);
-  EXPECT_FALSE(s.IsAccessControl());
-  EXPECT_FALSE(s.IsAlias());
-  EXPECT_FALSE(s.IsArray());
-  EXPECT_FALSE(s.IsBool());
-  EXPECT_FALSE(s.IsF32());
-  EXPECT_FALSE(s.IsI32());
-  EXPECT_FALSE(s.IsMatrix());
-  EXPECT_FALSE(s.IsPointer());
-  EXPECT_FALSE(s.IsSampler());
-  EXPECT_FALSE(s.IsStruct());
-  EXPECT_TRUE(s.IsTexture());
-  EXPECT_FALSE(s.IsU32());
-  EXPECT_FALSE(s.IsVector());
+  Type* ty = &s;
+  EXPECT_FALSE(ty->Is<AccessControlType>());
+  EXPECT_FALSE(ty->IsAlias());
+  EXPECT_FALSE(ty->IsArray());
+  EXPECT_FALSE(ty->IsBool());
+  EXPECT_FALSE(ty->IsF32());
+  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->IsPointer());
+  EXPECT_FALSE(ty->IsSampler());
+  EXPECT_FALSE(ty->IsStruct());
+  EXPECT_TRUE(ty->IsTexture());
+  EXPECT_FALSE(ty->IsU32());
+  EXPECT_FALSE(ty->IsVector());
 }
 
 TEST_F(SampledTextureTypeTest, IsTextureType) {
diff --git a/src/ast/type/sampler_type_test.cc b/src/ast/type/sampler_type_test.cc
index 5c348b3a51..263c93bda8 100644
--- a/src/ast/type/sampler_type_test.cc
+++ b/src/ast/type/sampler_type_test.cc
@@ -15,6 +15,7 @@
 #include "src/ast/type/sampler_type.h"
 
 #include "src/ast/test_helper.h"
+#include "src/ast/type/access_control_type.h"
 
 namespace tint {
 namespace ast {
@@ -36,19 +37,20 @@ TEST_F(SamplerTypeTest, Creation_ComparisonSampler) {
 
 TEST_F(SamplerTypeTest, Is) {
   SamplerType s{SamplerKind::kSampler};
-  EXPECT_FALSE(s.IsAccessControl());
-  EXPECT_FALSE(s.IsAlias());
-  EXPECT_FALSE(s.IsArray());
-  EXPECT_FALSE(s.IsBool());
-  EXPECT_FALSE(s.IsF32());
-  EXPECT_FALSE(s.IsI32());
-  EXPECT_FALSE(s.IsMatrix());
-  EXPECT_FALSE(s.IsPointer());
-  EXPECT_TRUE(s.IsSampler());
-  EXPECT_FALSE(s.IsStruct());
-  EXPECT_FALSE(s.IsTexture());
-  EXPECT_FALSE(s.IsU32());
-  EXPECT_FALSE(s.IsVector());
+  Type* ty = &s;
+  EXPECT_FALSE(ty->Is<AccessControlType>());
+  EXPECT_FALSE(ty->IsAlias());
+  EXPECT_FALSE(ty->IsArray());
+  EXPECT_FALSE(ty->IsBool());
+  EXPECT_FALSE(ty->IsF32());
+  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->IsPointer());
+  EXPECT_TRUE(ty->IsSampler());
+  EXPECT_FALSE(ty->IsStruct());
+  EXPECT_FALSE(ty->IsTexture());
+  EXPECT_FALSE(ty->IsU32());
+  EXPECT_FALSE(ty->IsVector());
 }
 
 TEST_F(SamplerTypeTest, TypeName_Sampler) {
diff --git a/src/ast/type/storage_texture_type_test.cc b/src/ast/type/storage_texture_type_test.cc
index dd5b32c359..4cd3af44ae 100644
--- a/src/ast/type/storage_texture_type_test.cc
+++ b/src/ast/type/storage_texture_type_test.cc
@@ -18,6 +18,7 @@
 
 #include "src/ast/identifier_expression.h"
 #include "src/ast/test_helper.h"
+#include "src/ast/type/access_control_type.h"
 #include "src/type_determiner.h"
 
 namespace tint {
@@ -30,19 +31,20 @@ using StorageTextureTypeTest = TestHelper;
 TEST_F(StorageTextureTypeTest, Is) {
   StorageTextureType s(TextureDimension::k2dArray, AccessControl::kReadOnly,
                        ImageFormat::kRgba32Float);
-  EXPECT_FALSE(s.IsAccessControl());
-  EXPECT_FALSE(s.IsAlias());
-  EXPECT_FALSE(s.IsArray());
-  EXPECT_FALSE(s.IsBool());
-  EXPECT_FALSE(s.IsF32());
-  EXPECT_FALSE(s.IsI32());
-  EXPECT_FALSE(s.IsMatrix());
-  EXPECT_FALSE(s.IsPointer());
-  EXPECT_FALSE(s.IsSampler());
-  EXPECT_FALSE(s.IsStruct());
-  EXPECT_TRUE(s.IsTexture());
-  EXPECT_FALSE(s.IsU32());
-  EXPECT_FALSE(s.IsVector());
+  Type* ty = &s;
+  EXPECT_FALSE(ty->Is<AccessControlType>());
+  EXPECT_FALSE(ty->IsAlias());
+  EXPECT_FALSE(ty->IsArray());
+  EXPECT_FALSE(ty->IsBool());
+  EXPECT_FALSE(ty->IsF32());
+  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->IsPointer());
+  EXPECT_FALSE(ty->IsSampler());
+  EXPECT_FALSE(ty->IsStruct());
+  EXPECT_TRUE(ty->IsTexture());
+  EXPECT_FALSE(ty->IsU32());
+  EXPECT_FALSE(ty->IsVector());
 }
 
 TEST_F(StorageTextureTypeTest, IsTextureType) {
diff --git a/src/ast/type/struct_type_test.cc b/src/ast/type/struct_type_test.cc
index 88bf368688..9d83f01cc0 100644
--- a/src/ast/type/struct_type_test.cc
+++ b/src/ast/type/struct_type_test.cc
@@ -21,6 +21,7 @@
 #include "src/ast/struct_member_decoration.h"
 #include "src/ast/struct_member_offset_decoration.h"
 #include "src/ast/test_helper.h"
+#include "src/ast/type/access_control_type.h"
 #include "src/ast/type/array_type.h"
 #include "src/ast/type/i32_type.h"
 #include "src/ast/type/u32_type.h"
@@ -43,19 +44,20 @@ TEST_F(StructTypeTest, Creation) {
 TEST_F(StructTypeTest, Is) {
   auto* impl = create<Struct>();
   StructType s{"S", impl};
-  EXPECT_FALSE(s.IsAccessControl());
-  EXPECT_FALSE(s.IsAlias());
-  EXPECT_FALSE(s.IsArray());
-  EXPECT_FALSE(s.IsBool());
-  EXPECT_FALSE(s.IsF32());
-  EXPECT_FALSE(s.IsI32());
-  EXPECT_FALSE(s.IsMatrix());
-  EXPECT_FALSE(s.IsPointer());
-  EXPECT_FALSE(s.IsSampler());
-  EXPECT_TRUE(s.IsStruct());
-  EXPECT_FALSE(s.IsTexture());
-  EXPECT_FALSE(s.IsU32());
-  EXPECT_FALSE(s.IsVector());
+  Type* ty = &s;
+  EXPECT_FALSE(ty->Is<AccessControlType>());
+  EXPECT_FALSE(ty->IsAlias());
+  EXPECT_FALSE(ty->IsArray());
+  EXPECT_FALSE(ty->IsBool());
+  EXPECT_FALSE(ty->IsF32());
+  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->IsPointer());
+  EXPECT_FALSE(ty->IsSampler());
+  EXPECT_TRUE(ty->IsStruct());
+  EXPECT_FALSE(ty->IsTexture());
+  EXPECT_FALSE(ty->IsU32());
+  EXPECT_FALSE(ty->IsVector());
 }
 
 TEST_F(StructTypeTest, TypeName) {
diff --git a/src/ast/type/type.cc b/src/ast/type/type.cc
index 51c48f03ad..9587688e6d 100644
--- a/src/ast/type/type.cc
+++ b/src/ast/type/type.cc
@@ -37,7 +37,7 @@ namespace type {
 
 Type::Type() = default;
 
-Type::  Type(Type&&) = default;
+Type::Type(Type&&) = default;
 
 Type::~Type() = default;
 
@@ -52,9 +52,9 @@ Type* Type::UnwrapIfNeeded() {
   auto* where = this;
   while (true) {
     if (where->IsAlias()) {
-          where = where->AsAlias()->type();
-    } else if (where->IsAccessControl()) {
-          where = where->AsAccessControl()->type();
+      where = where->AsAlias()->type();
+    } else if (where->Is<AccessControlType>()) {
+      where = where->As<AccessControlType>()->type();
     } else {
       break;
     }
@@ -66,10 +66,6 @@ Type* Type::UnwrapAll() {
   return UnwrapIfNeeded()->UnwrapPtrIfNeeded()->UnwrapIfNeeded();
 }
 
-bool Type::IsAccessControl() const {
-  return false;
-}
-
 bool Type::IsAlias() const {
   return false;
 }
@@ -174,11 +170,6 @@ bool Type::is_integer_scalar_or_vector() {
   return is_unsigned_scalar_or_vector() || is_signed_scalar_or_vector();
 }
 
-const AccessControlType* Type::AsAccessControl() const {
-  assert(IsAccessControl());
-  return static_cast<const AccessControlType*>(this);
-}
-
 const AliasType* Type::AsAlias() const {
   assert(IsAlias());
   return static_cast<const AliasType*>(this);
@@ -244,11 +235,6 @@ const VoidType* Type::AsVoid() const {
   return static_cast<const VoidType*>(this);
 }
 
-AccessControlType* Type::AsAccessControl() {
-  assert(IsAccessControl());
-  return static_cast<AccessControlType*>(this);
-}
-
 AliasType* Type::AsAlias() {
   assert(IsAlias());
   return static_cast<AliasType*>(this);
diff --git a/src/ast/type/type.h b/src/ast/type/type.h
index 17cd265d26..ad83af92ad 100644
--- a/src/ast/type/type.h
+++ b/src/ast/type/type.h
@@ -23,7 +23,6 @@ namespace tint {
 namespace ast {
 namespace type {
 
-class AccessControlType;
 class AliasType;
 class ArrayType;
 class BoolType;
@@ -48,8 +47,6 @@ class Type : public Castable<Type> {
   Type(Type&&);
   ~Type() override;
 
-  /// @returns true if the type is an access control type
-  virtual bool IsAccessControl() const;
   /// @returns true if the type is an alias type
   virtual bool IsAlias() const;
   /// @returns true if the type is an array type
@@ -131,8 +128,6 @@ class Type : public Castable<Type> {
   /// @returns true if this type is an integer scalar or vector
   bool is_integer_scalar_or_vector();
 
-  /// @returns the type as an access control type
-  const AccessControlType* AsAccessControl() const;
   /// @returns the type as an alias type
   const AliasType* AsAlias() const;
   /// @returns the type as an array type
@@ -160,8 +155,6 @@ class Type : public Castable<Type> {
   /// @returns the type as a void type
   const VoidType* AsVoid() const;
 
-  /// @returns the type as an access control type
-  AccessControlType* AsAccessControl();
   /// @returns the type as an alias type
   AliasType* AsAlias();
   /// @returns the type as an array type
diff --git a/src/ast/type/u32_type_test.cc b/src/ast/type/u32_type_test.cc
index 0d6ec7e88d..0a8af4b077 100644
--- a/src/ast/type/u32_type_test.cc
+++ b/src/ast/type/u32_type_test.cc
@@ -15,6 +15,7 @@
 #include "src/ast/type/u32_type.h"
 
 #include "src/ast/test_helper.h"
+#include "src/ast/type/access_control_type.h"
 
 namespace tint {
 namespace ast {
@@ -25,19 +26,20 @@ using U32TypeTest = TestHelper;
 
 TEST_F(U32TypeTest, Is) {
   U32Type u;
-  EXPECT_FALSE(u.IsAccessControl());
-  EXPECT_FALSE(u.IsAlias());
-  EXPECT_FALSE(u.IsArray());
-  EXPECT_FALSE(u.IsBool());
-  EXPECT_FALSE(u.IsF32());
-  EXPECT_FALSE(u.IsI32());
-  EXPECT_FALSE(u.IsMatrix());
-  EXPECT_FALSE(u.IsPointer());
-  EXPECT_FALSE(u.IsSampler());
-  EXPECT_FALSE(u.IsStruct());
-  EXPECT_FALSE(u.IsTexture());
-  EXPECT_TRUE(u.IsU32());
-  EXPECT_FALSE(u.IsVector());
+  Type* ty = &u;
+  EXPECT_FALSE(ty->Is<AccessControlType>());
+  EXPECT_FALSE(ty->IsAlias());
+  EXPECT_FALSE(ty->IsArray());
+  EXPECT_FALSE(ty->IsBool());
+  EXPECT_FALSE(ty->IsF32());
+  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->IsPointer());
+  EXPECT_FALSE(ty->IsSampler());
+  EXPECT_FALSE(ty->IsStruct());
+  EXPECT_FALSE(ty->IsTexture());
+  EXPECT_TRUE(ty->IsU32());
+  EXPECT_FALSE(ty->IsVector());
 }
 
 TEST_F(U32TypeTest, TypeName) {
diff --git a/src/ast/type/vector_type_test.cc b/src/ast/type/vector_type_test.cc
index dbc0833190..3eed2cf8a5 100644
--- a/src/ast/type/vector_type_test.cc
+++ b/src/ast/type/vector_type_test.cc
@@ -15,6 +15,7 @@
 #include "src/ast/type/vector_type.h"
 
 #include "src/ast/test_helper.h"
+#include "src/ast/type/access_control_type.h"
 #include "src/ast/type/i32_type.h"
 
 namespace tint {
@@ -34,19 +35,20 @@ TEST_F(VectorTypeTest, Creation) {
 TEST_F(VectorTypeTest, Is) {
   I32Type i32;
   VectorType v{&i32, 4};
-  EXPECT_FALSE(v.IsAccessControl());
-  EXPECT_FALSE(v.IsAlias());
-  EXPECT_FALSE(v.IsArray());
-  EXPECT_FALSE(v.IsBool());
-  EXPECT_FALSE(v.IsF32());
-  EXPECT_FALSE(v.IsI32());
-  EXPECT_FALSE(v.IsMatrix());
-  EXPECT_FALSE(v.IsPointer());
-  EXPECT_FALSE(v.IsSampler());
-  EXPECT_FALSE(v.IsStruct());
-  EXPECT_FALSE(v.IsTexture());
-  EXPECT_FALSE(v.IsU32());
-  EXPECT_TRUE(v.IsVector());
+  Type* ty = &v;
+  EXPECT_FALSE(ty->Is<AccessControlType>());
+  EXPECT_FALSE(ty->IsAlias());
+  EXPECT_FALSE(ty->IsArray());
+  EXPECT_FALSE(ty->IsBool());
+  EXPECT_FALSE(ty->IsF32());
+  EXPECT_FALSE(ty->IsI32());
+  EXPECT_FALSE(ty->IsMatrix());
+  EXPECT_FALSE(ty->IsPointer());
+  EXPECT_FALSE(ty->IsSampler());
+  EXPECT_FALSE(ty->IsStruct());
+  EXPECT_FALSE(ty->IsTexture());
+  EXPECT_FALSE(ty->IsU32());
+  EXPECT_TRUE(ty->IsVector());
 }
 
 TEST_F(VectorTypeTest, TypeName) {
diff --git a/src/inspector/inspector.cc b/src/inspector/inspector.cc
index 9875ec40f3..7e7bb158ab 100644
--- a/src/inspector/inspector.cc
+++ b/src/inspector/inspector.cc
@@ -181,7 +181,7 @@ std::vector<ResourceBinding> Inspector::GetUniformBufferResourceBindings(
     ast::Variable* var = nullptr;
     ast::Function::BindingInfo binding_info;
     std::tie(var, binding_info) = ruv;
-    if (!var->type()->IsAccessControl()) {
+    if (!var->type()->Is<ast::type::AccessControlType>()) {
       continue;
     }
     auto* unwrapped_type = var->type()->UnwrapIfNeeded();
@@ -303,11 +303,11 @@ std::vector<ResourceBinding> Inspector::GetStorageBufferResourceBindingsImpl(
     ast::Variable* var = nullptr;
     ast::Function::BindingInfo binding_info;
     std::tie(var, binding_info) = rsv;
-    if (!var->type()->IsAccessControl()) {
+    if (!var->type()->Is<ast::type::AccessControlType>()) {
       continue;
     }
 
-    auto* ac_type = var->type()->AsAccessControl();
+    auto* ac_type = var->type()->As<ast::type::AccessControlType>();
     if (read_only != ac_type->IsReadOnly()) {
       continue;
     }
diff --git a/src/reader/wgsl/parser_impl_variable_ident_decl_test.cc b/src/reader/wgsl/parser_impl_variable_ident_decl_test.cc
index 2ace2a96dd..6a6fd7474c 100644
--- a/src/reader/wgsl/parser_impl_variable_ident_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_ident_decl_test.cc
@@ -103,8 +103,8 @@ TEST_F(ParserImplTest, VariableIdentDecl_ParsesWithAccessDeco_Read) {
   ASSERT_FALSE(decl.errored);
   ASSERT_EQ(decl->name, "my_var");
   ASSERT_NE(decl->type, nullptr);
-  ASSERT_TRUE(decl->type->IsAccessControl());
-  EXPECT_TRUE(decl->type->AsAccessControl()->IsReadOnly());
+  ASSERT_TRUE(decl->type->Is<ast::type::AccessControlType>());
+  EXPECT_TRUE(decl->type->As<ast::type::AccessControlType>()->IsReadOnly());
 }
 
 TEST_F(ParserImplTest, VariableIdentDecl_ParsesWithAccessDeco_ReadWrite) {
@@ -129,8 +129,8 @@ TEST_F(ParserImplTest, VariableIdentDecl_ParsesWithAccessDeco_ReadWrite) {
   ASSERT_FALSE(decl.errored);
   ASSERT_EQ(decl->name, "my_var");
   ASSERT_NE(decl->type, nullptr);
-  ASSERT_TRUE(decl->type->IsAccessControl());
-  EXPECT_TRUE(decl->type->AsAccessControl()->IsReadWrite());
+  ASSERT_TRUE(decl->type->Is<ast::type::AccessControlType>());
+  EXPECT_TRUE(decl->type->As<ast::type::AccessControlType>()->IsReadWrite());
 }
 
 TEST_F(ParserImplTest, VariableIdentDecl_MultipleAccessDecoFail) {
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index 0d2da92c00..2e62109dcb 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -1328,11 +1328,11 @@ bool GeneratorImpl::EmitEntryPointData(
     }
     emitted_globals.insert(var->name());
 
-    if (!var->type()->IsAccessControl()) {
+    if (!var->type()->Is<ast::type::AccessControlType>()) {
       error_ = "access control type required for storage buffer";
       return false;
     }
-    auto* ac = var->type()->AsAccessControl();
+    auto* ac = var->type()->As<ast::type::AccessControlType>();
 
     if (ac->IsReadWrite()) {
       out << "RW";
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index a7fe3237fe..0f1b2e353b 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -1282,11 +1282,11 @@ bool GeneratorImpl::EmitFunctionInternal(ast::Function* func,
     }
     first = false;
 
-    if (!var->type()->IsAccessControl()) {
+    if (!var->type()->Is<ast::type::AccessControlType>()) {
       error_ = "invalid type for storage buffer, expected access control";
       return false;
     }
-    auto* ac = var->type()->AsAccessControl();
+    auto* ac = var->type()->As<ast::type::AccessControlType>();
     if (ac->IsReadOnly()) {
       out_ << "const ";
     }
@@ -1443,11 +1443,11 @@ bool GeneratorImpl::EmitEntryPointFunction(ast::Function* func) {
     auto* binding = data.second.binding;
     // auto* set = data.second.set;
 
-    if (!var->type()->IsAccessControl()) {
+    if (!var->type()->Is<ast::type::AccessControlType>()) {
       error_ = "invalid type for storage buffer, expected access control";
       return false;
     }
-    auto* ac = var->type()->AsAccessControl();
+    auto* ac = var->type()->As<ast::type::AccessControlType>();
     if (ac->IsReadOnly()) {
       out_ << "const ";
     }
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index b0925e9855..6e8c932f22 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -2399,8 +2399,8 @@ uint32_t Builder::GenerateTypeIfNeeded(ast::type::Type* type) {
   auto result = result_op();
   auto id = result.to_i();
 
-  if (type->IsAccessControl()) {
-    auto* ac = type->AsAccessControl();
+  if (type->Is<ast::type::AccessControlType>()) {
+    auto* ac = type->As<ast::type::AccessControlType>();
     auto* subtype = ac->type()->UnwrapIfNeeded();
     if (!subtype->IsStruct()) {
       error_ = "Access control attached to non-struct type.";
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc
index 7c49dd22ad..16dfb9e3f8 100644
--- a/src/writer/wgsl/generator_impl.cc
+++ b/src/writer/wgsl/generator_impl.cc
@@ -394,8 +394,8 @@ bool GeneratorImpl::EmitImageFormat(const ast::type::ImageFormat fmt) {
 }
 
 bool GeneratorImpl::EmitType(ast::type::Type* type) {
-  if (type->IsAccessControl()) {
-    auto* ac = type->AsAccessControl();
+  if (type->Is<ast::type::AccessControlType>()) {
+    auto* ac = type->As<ast::type::AccessControlType>();
 
     out_ << "[[access(";
     if (ac->IsReadOnly()) {