Post migration to castable cleanup

Change-Id: I5c47b1736bd850548cb1c9c7a6f69242d8626173
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/34460
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/ast/function.cc b/src/ast/function.cc
index e3c5ca2..5f53799 100644
--- a/src/ast/function.cc
+++ b/src/ast/function.cc
@@ -104,25 +104,26 @@
   std::vector<std::pair<Variable*, Function::BindingInfo>> ret;
 
   for (auto* var : referenced_module_variables()) {
-    if (!var->Is<DecoratedVariable>() ||
-        var->storage_class() != StorageClass::kUniform) {
+    if (var->storage_class() != StorageClass::kUniform) {
       continue;
     }
 
-    BindingDecoration* binding = nullptr;
-    SetDecoration* set = nullptr;
-    for (auto* deco : var->As<DecoratedVariable>()->decorations()) {
-      if (auto* b = deco->As<BindingDecoration>()) {
-        binding = b;
-      } else if (auto* s = deco->As<SetDecoration>()) {
-        set = s;
+    if (auto* decorated = var->As<DecoratedVariable>()) {
+      BindingDecoration* binding = nullptr;
+      SetDecoration* set = nullptr;
+      for (auto* deco : decorated->decorations()) {
+        if (auto* b = deco->As<BindingDecoration>()) {
+          binding = b;
+        } else if (auto* s = deco->As<SetDecoration>()) {
+          set = s;
+        }
       }
-    }
-    if (binding == nullptr || set == nullptr) {
-      continue;
-    }
+      if (binding == nullptr || set == nullptr) {
+        continue;
+      }
 
-    ret.push_back({var, BindingInfo{binding, set}});
+      ret.push_back({var, BindingInfo{binding, set}});
+    }
   }
   return ret;
 }
@@ -132,25 +133,26 @@
   std::vector<std::pair<Variable*, Function::BindingInfo>> ret;
 
   for (auto* var : referenced_module_variables()) {
-    if (!var->Is<DecoratedVariable>() ||
-        var->storage_class() != StorageClass::kStorageBuffer) {
+    if (var->storage_class() != StorageClass::kStorageBuffer) {
       continue;
     }
 
-    BindingDecoration* binding = nullptr;
-    SetDecoration* set = nullptr;
-    for (auto* deco : var->As<DecoratedVariable>()->decorations()) {
-      if (auto* b = deco->As<BindingDecoration>()) {
-        binding = b;
-      } else if (auto* s = deco->As<SetDecoration>()) {
-        set = s;
+    if (auto* decorated = var->As<DecoratedVariable>()) {
+      BindingDecoration* binding = nullptr;
+      SetDecoration* set = nullptr;
+      for (auto* deco : decorated->decorations()) {
+        if (auto* b = deco->As<BindingDecoration>()) {
+          binding = b;
+        } else if (auto* s = deco->As<SetDecoration>()) {
+          set = s;
+        }
       }
-    }
-    if (binding == nullptr || set == nullptr) {
-      continue;
-    }
+      if (binding == nullptr || set == nullptr) {
+        continue;
+      }
 
-    ret.push_back({var, BindingInfo{binding, set}});
+      ret.push_back({var, BindingInfo{binding, set}});
+    }
   }
   return ret;
 }
@@ -160,13 +162,12 @@
   std::vector<std::pair<Variable*, BuiltinDecoration*>> ret;
 
   for (auto* var : referenced_module_variables()) {
-    if (!var->Is<DecoratedVariable>()) {
-      continue;
-    }
-    for (auto* deco : var->As<DecoratedVariable>()->decorations()) {
-      if (auto* builtin = deco->As<BuiltinDecoration>()) {
-        ret.push_back({var, builtin});
-        break;
+    if (auto* decorated = var->As<DecoratedVariable>()) {
+      for (auto* deco : decorated->decorations()) {
+        if (auto* builtin = deco->As<BuiltinDecoration>()) {
+          ret.push_back({var, builtin});
+          break;
+        }
       }
     }
   }
@@ -292,25 +293,28 @@
 
   for (auto* var : referenced_module_variables()) {
     auto* unwrapped_type = var->type()->UnwrapIfNeeded();
-    if (!var->Is<DecoratedVariable>() || !unwrapped_type->Is<type::Sampler>() ||
-        unwrapped_type->As<type::Sampler>()->kind() != kind) {
+    auto* sampler = unwrapped_type->As<type::Sampler>();
+    if (sampler == nullptr || sampler->kind() != kind) {
       continue;
     }
 
-    BindingDecoration* binding = nullptr;
-    SetDecoration* set = nullptr;
-    for (auto* deco : var->As<DecoratedVariable>()->decorations()) {
-      if (auto* b = deco->As<BindingDecoration>()) {
-        binding = b;
-      } else if (auto* s = deco->As<SetDecoration>()) {
-        set = s;
+    if (auto* decorated = var->As<DecoratedVariable>()) {
+      BindingDecoration* binding = nullptr;
+      SetDecoration* set = nullptr;
+      for (auto* deco : decorated->decorations()) {
+        if (auto* b = deco->As<BindingDecoration>()) {
+          binding = b;
+        }
+        if (auto* s = deco->As<SetDecoration>()) {
+          set = s;
+        }
       }
-    }
-    if (binding == nullptr || set == nullptr) {
-      continue;
-    }
+      if (binding == nullptr || set == nullptr) {
+        continue;
+      }
 
-    ret.push_back({var, BindingInfo{binding, set}});
+      ret.push_back({var, BindingInfo{binding, set}});
+    }
   }
   return ret;
 }
@@ -321,29 +325,34 @@
 
   for (auto* var : referenced_module_variables()) {
     auto* unwrapped_type = var->type()->UnwrapIfNeeded();
-    if (!var->Is<DecoratedVariable>() || !unwrapped_type->Is<type::Texture>()) {
+    auto* texture = unwrapped_type->As<type::Texture>();
+    if (texture == nullptr) {
       continue;
     }
 
-    if ((multisampled && !unwrapped_type->Is<type::MultisampledTexture>()) ||
-        (!multisampled && !unwrapped_type->Is<type::SampledTexture>())) {
+    auto is_multisampled = texture->Is<type::MultisampledTexture>();
+    auto is_sampled = texture->Is<type::SampledTexture>();
+
+    if ((multisampled && !is_multisampled) || (!multisampled && !is_sampled)) {
       continue;
     }
 
-    BindingDecoration* binding = nullptr;
-    SetDecoration* set = nullptr;
-    for (auto* deco : var->As<DecoratedVariable>()->decorations()) {
-      if (auto* b = deco->As<BindingDecoration>()) {
-        binding = b;
-      } else if (auto* s = deco->As<SetDecoration>()) {
-        set = s;
+    if (auto* decorated = var->As<DecoratedVariable>()) {
+      BindingDecoration* binding = nullptr;
+      SetDecoration* set = nullptr;
+      for (auto* deco : decorated->decorations()) {
+        if (auto* b = deco->As<BindingDecoration>()) {
+          binding = b;
+        } else if (auto* s = deco->As<SetDecoration>()) {
+          set = s;
+        }
       }
-    }
-    if (binding == nullptr || set == nullptr) {
-      continue;
-    }
+      if (binding == nullptr || set == nullptr) {
+        continue;
+      }
 
-    ret.push_back({var, BindingInfo{binding, set}});
+      ret.push_back({var, BindingInfo{binding, set}});
+    }
   }
 
   return ret;
diff --git a/src/ast/module.cc b/src/ast/module.cc
index e9fecf1..fd2090d 100644
--- a/src/ast/module.cc
+++ b/src/ast/module.cc
@@ -74,17 +74,16 @@
     if (ty == nullptr) {
       return false;
     }
-    if (ty->Is<type::Alias>()) {
-      auto* alias = ty->As<type::Alias>();
+    if (auto* alias = ty->As<type::Alias>()) {
       if (alias->type() == nullptr) {
         return false;
       }
-      if (alias->type()->Is<type::Struct>() &&
-          alias->type()->As<type::Struct>()->name().empty()) {
-        return false;
+      if (auto* str = alias->type()->As<type::Struct>()) {
+        if (str->name().empty()) {
+          return false;
+        }
       }
-    } else if (ty->Is<type::Struct>()) {
-      auto* str = ty->As<type::Struct>();
+    } else if (auto* str = ty->As<type::Struct>()) {
       if (str->name().empty()) {
         return false;
       }
@@ -109,14 +108,12 @@
     for (size_t i = 0; i < indent; ++i) {
       out << " ";
     }
-    if (ty->Is<type::Alias>()) {
-      auto* alias = ty->As<type::Alias>();
+    if (auto* alias = ty->As<type::Alias>()) {
       out << alias->name() << " -> " << alias->type()->type_name() << std::endl;
-      if (alias->type()->Is<type::Struct>()) {
-        alias->type()->As<type::Struct>()->impl()->to_str(out, indent);
+      if (auto* str = alias->type()->As<type::Struct>()) {
+        str->impl()->to_str(out, indent);
       }
-    } else if (ty->Is<type::Struct>()) {
-      auto* str = ty->As<type::Struct>();
+    } else if (auto* str = ty->As<type::Struct>()) {
       out << str->name() << " ";
       str->impl()->to_str(out, indent);
     }
diff --git a/src/ast/type/storage_texture_type_test.cc b/src/ast/type/storage_texture_type_test.cc
index 6eb20a5..95289ff 100644
--- a/src/ast/type/storage_texture_type_test.cc
+++ b/src/ast/type/storage_texture_type_test.cc
@@ -102,7 +102,7 @@
   ASSERT_TRUE(td.Determine()) << td.error();
   ASSERT_TRUE(s->Is<Texture>());
   ASSERT_TRUE(s->Is<StorageTexture>());
-  EXPECT_TRUE(s->As<Texture>()->As<StorageTexture>()->type()->Is<F32>());
+  EXPECT_TRUE(s->As<StorageTexture>()->type()->Is<F32>());
 }
 
 TEST_F(StorageTextureTest, U32) {
@@ -130,7 +130,7 @@
   ASSERT_TRUE(td.Determine()) << td.error();
   ASSERT_TRUE(s->Is<Texture>());
   ASSERT_TRUE(s->Is<StorageTexture>());
-  EXPECT_TRUE(s->As<Texture>()->As<StorageTexture>()->type()->Is<I32>());
+  EXPECT_TRUE(s->As<StorageTexture>()->type()->Is<I32>());
 }
 
 TEST_F(StorageTextureTest, MinBufferBindingSize) {
diff --git a/src/ast/type/type.cc b/src/ast/type/type.cc
index e1d7b1a..e424ee7 100644
--- a/src/ast/type/type.cc
+++ b/src/ast/type/type.cc
@@ -42,8 +42,8 @@
 Type::~Type() = default;
 
 Type* Type::UnwrapPtrIfNeeded() {
-  if (Is<Pointer>()) {
-    return As<Pointer>()->type();
+  if (auto* ptr = As<type::Pointer>()) {
+    return ptr->type();
   }
   return this;
 }
@@ -51,10 +51,10 @@
 Type* Type::UnwrapIfNeeded() {
   auto* where = this;
   while (true) {
-    if (where->Is<Alias>()) {
-      where = where->As<Alias>()->type();
-    } else if (where->Is<AccessControl>()) {
-      where = where->As<AccessControl>()->type();
+    if (auto* alias = where->As<type::Alias>()) {
+      where = alias->type();
+    } else if (auto* access = where->As<type::AccessControl>()) {
+      where = access->type();
     } else {
       break;
     }
diff --git a/src/inspector/inspector.cc b/src/inspector/inspector.cc
index 7f18ed4..9914d85 100644
--- a/src/inspector/inspector.cc
+++ b/src/inspector/inspector.cc
@@ -124,44 +124,45 @@
     }
 
     auto* expression = var->constructor();
-    if (!expression->Is<ast::ConstructorExpression>()) {
-      // This is invalid WGSL, but handling gracefully.
-      result[constant_id] = Scalar();
-      continue;
-    }
-
     auto* constructor = expression->As<ast::ConstructorExpression>();
-    if (!constructor->Is<ast::ScalarConstructorExpression>()) {
+    if (constructor == nullptr) {
       // This is invalid WGSL, but handling gracefully.
       result[constant_id] = Scalar();
       continue;
     }
 
-    auto* literal =
-        constructor->As<ast::ScalarConstructorExpression>()->literal();
+    auto* scalar_constructor =
+        constructor->As<ast::ScalarConstructorExpression>();
+    if (scalar_constructor == nullptr) {
+      // This is invalid WGSL, but handling gracefully.
+      result[constant_id] = Scalar();
+      continue;
+    }
+
+    auto* literal = scalar_constructor->literal();
     if (!literal) {
       // This is invalid WGSL, but handling gracefully.
       result[constant_id] = Scalar();
       continue;
     }
 
-    if (literal->Is<ast::BoolLiteral>()) {
-      result[constant_id] = Scalar(literal->As<ast::BoolLiteral>()->IsTrue());
+    if (auto* l = literal->As<ast::BoolLiteral>()) {
+      result[constant_id] = Scalar(l->IsTrue());
       continue;
     }
 
-    if (literal->Is<ast::UintLiteral>()) {
-      result[constant_id] = Scalar(literal->As<ast::UintLiteral>()->value());
+    if (auto* l = literal->As<ast::UintLiteral>()) {
+      result[constant_id] = Scalar(l->value());
       continue;
     }
 
-    if (literal->Is<ast::SintLiteral>()) {
-      result[constant_id] = Scalar(literal->As<ast::SintLiteral>()->value());
+    if (auto* l = literal->As<ast::SintLiteral>()) {
+      result[constant_id] = Scalar(l->value());
       continue;
     }
 
-    if (literal->Is<ast::FloatLiteral>()) {
-      result[constant_id] = Scalar(literal->As<ast::FloatLiteral>()->value());
+    if (auto* l = literal->As<ast::FloatLiteral>()) {
+      result[constant_id] = Scalar(l->value());
       continue;
     }
 
@@ -190,11 +191,12 @@
     }
     auto* unwrapped_type = var->type()->UnwrapIfNeeded();
 
-    if (!unwrapped_type->Is<ast::type::Struct>()) {
+    auto* str = unwrapped_type->As<ast::type::Struct>();
+    if (str == nullptr) {
       continue;
     }
 
-    if (!unwrapped_type->As<ast::type::Struct>()->IsBlockDecorated()) {
+    if (!str->IsBlockDecorated()) {
       continue;
     }
 
@@ -307,11 +309,12 @@
     ast::Variable* var = nullptr;
     ast::Function::BindingInfo binding_info;
     std::tie(var, binding_info) = rsv;
-    if (!var->type()->Is<ast::type::AccessControl>()) {
+
+    auto* ac_type = var->type()->As<ast::type::AccessControl>();
+    if (ac_type == nullptr) {
       continue;
     }
 
-    auto* ac_type = var->type()->As<ast::type::AccessControl>();
     if (read_only != ac_type->IsReadOnly()) {
       continue;
     }
@@ -392,12 +395,12 @@
                       ->UnwrapIfNeeded();
     }
 
-    if (base_type->Is<ast::type::Array>()) {
-      base_type = base_type->As<ast::type::Array>()->type();
-    } else if (base_type->Is<ast::type::Matrix>()) {
-      base_type = base_type->As<ast::type::Matrix>()->type();
-    } else if (base_type->Is<ast::type::Vector>()) {
-      base_type = base_type->As<ast::type::Vector>()->type();
+    if (auto* at = base_type->As<ast::type::Array>()) {
+      base_type = at->type();
+    } else if (auto* mt = base_type->As<ast::type::Matrix>()) {
+      base_type = mt->type();
+    } else if (auto* vt = base_type->As<ast::type::Vector>()) {
+      base_type = vt->type();
     }
 
     if (base_type->Is<ast::type::F32>()) {
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index 975ca26..30b74b1 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -2267,11 +2267,11 @@
   // A continue construct has the same depth as its associated loop
   // construct. Start a continue construct.
   auto* loop_candidate = LastStatement();
-  if (!loop_candidate->Is<ast::LoopStatement>()) {
+  auto* loop = loop_candidate->As<ast::LoopStatement>();
+  if (loop == nullptr) {
     return Fail() << "internal error: starting continue construct, "
                      "expected loop on top of stack";
   }
-  auto* loop = loop_candidate->As<ast::LoopStatement>();
   PushNewStatementBlock(
       construct, construct->end_id,
       [loop](StatementBlock* s) { loop->set_continuing(s->statements_); });
@@ -3268,10 +3268,10 @@
       const auto* type = type_mgr_->GetType(inst.type_id());
       if (type) {
         if (type->AsPointer()) {
-          const auto* ast_type = parser_impl_.ConvertType(inst.type_id());
-          if (ast_type && ast_type->As<ast::type::Pointer>()) {
-            info->storage_class =
-                ast_type->As<ast::type::Pointer>()->storage_class();
+          if (const auto* ast_type = parser_impl_.ConvertType(inst.type_id())) {
+            if (auto* ptr = ast_type->As<ast::type::Pointer>()) {
+              info->storage_class = ptr->storage_class();
+            }
           }
           switch (inst.opcode()) {
             case SpvOpUndef:
@@ -3322,10 +3322,9 @@
 
 ast::type::Type* FunctionEmitter::RemapStorageClass(ast::type::Type* type,
                                                     uint32_t result_id) {
-  if (type->Is<ast::type::Pointer>()) {
+  if (const auto* ast_ptr_type = type->As<ast::type::Pointer>()) {
     // Remap an old-style storage buffer pointer to a new-style storage
     // buffer pointer.
-    const auto* ast_ptr_type = type->As<ast::type::Pointer>();
     const auto sc = GetStorageClassForPointerValue(result_id);
     if (ast_ptr_type->storage_class() != sc) {
       return parser_impl_.get_module().create<ast::type::Pointer>(
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index 6ee2251..ccdf5c5 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -1349,8 +1349,7 @@
     return create<ast::ScalarConstructorExpression>(
         create<ast::FloatLiteral>(type, 0.0f));
   }
-  if (type->Is<ast::type::Vector>()) {
-    const auto* vec_ty = type->As<ast::type::Vector>();
+  if (const auto* vec_ty = type->As<ast::type::Vector>()) {
     ast::ExpressionList ast_components;
     for (size_t i = 0; i < vec_ty->size(); ++i) {
       ast_components.emplace_back(MakeNullValue(vec_ty->type()));
@@ -1358,8 +1357,7 @@
     return create<ast::TypeConstructorExpression>(type,
                                                   std::move(ast_components));
   }
-  if (type->Is<ast::type::Matrix>()) {
-    const auto* mat_ty = type->As<ast::type::Matrix>();
+  if (const auto* mat_ty = type->As<ast::type::Matrix>()) {
     // Matrix components are columns
     auto* column_ty =
         ast_module_.create<ast::type::Vector>(mat_ty->type(), mat_ty->rows());
@@ -1370,8 +1368,7 @@
     return create<ast::TypeConstructorExpression>(type,
                                                   std::move(ast_components));
   }
-  if (type->Is<ast::type::Array>()) {
-    auto* arr_ty = type->As<ast::type::Array>();
+  if (auto* arr_ty = type->As<ast::type::Array>()) {
     ast::ExpressionList ast_components;
     for (size_t i = 0; i < arr_ty->size(); ++i) {
       ast_components.emplace_back(MakeNullValue(arr_ty->type()));
@@ -1379,8 +1376,7 @@
     return create<ast::TypeConstructorExpression>(original_type,
                                                   std::move(ast_components));
   }
-  if (type->Is<ast::type::Struct>()) {
-    auto* struct_ty = type->As<ast::type::Struct>();
+  if (auto* struct_ty = type->As<ast::type::Struct>()) {
     ast::ExpressionList ast_components;
     for (auto* member : struct_ty->impl()->members()) {
       ast_components.emplace_back(MakeNullValue(member->type()));
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index ff79577..ada6e78 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -2941,8 +2941,8 @@
   std::vector<T*> out;
   out.reserve(in.size());
   for (auto* deco : in) {
-    if (deco->Is<T>()) {
-      out.emplace_back(deco->As<T>());
+    if (auto* t = deco->As<T>()) {
+      out.emplace_back(t);
     } else {
       remaining.emplace_back(deco);
     }
diff --git a/src/reader/wgsl/parser_impl_depth_texture_type_test.cc b/src/reader/wgsl/parser_impl_depth_texture_type_test.cc
index 5ba850e..2e12319 100644
--- a/src/reader/wgsl/parser_impl_depth_texture_type_test.cc
+++ b/src/reader/wgsl/parser_impl_depth_texture_type_test.cc
@@ -37,7 +37,7 @@
   EXPECT_FALSE(t.errored);
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::type::Texture>());
-  ASSERT_TRUE(t->As<ast::type::Texture>()->Is<ast::type::DepthTexture>());
+  ASSERT_TRUE(t->Is<ast::type::DepthTexture>());
   EXPECT_EQ(t->As<ast::type::Texture>()->dim(),
             ast::type::TextureDimension::k2d);
   EXPECT_FALSE(p->has_error());
@@ -50,7 +50,7 @@
   EXPECT_FALSE(t.errored);
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::type::Texture>());
-  ASSERT_TRUE(t->As<ast::type::Texture>()->Is<ast::type::DepthTexture>());
+  ASSERT_TRUE(t->Is<ast::type::DepthTexture>());
   EXPECT_EQ(t->As<ast::type::Texture>()->dim(),
             ast::type::TextureDimension::k2dArray);
   EXPECT_FALSE(p->has_error());
@@ -63,7 +63,7 @@
   EXPECT_FALSE(t.errored);
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::type::Texture>());
-  ASSERT_TRUE(t->As<ast::type::Texture>()->Is<ast::type::DepthTexture>());
+  ASSERT_TRUE(t->Is<ast::type::DepthTexture>());
   EXPECT_EQ(t->As<ast::type::Texture>()->dim(),
             ast::type::TextureDimension::kCube);
   EXPECT_FALSE(p->has_error());
@@ -76,7 +76,7 @@
   EXPECT_FALSE(t.errored);
   ASSERT_NE(t.value, nullptr);
   ASSERT_TRUE(t->Is<ast::type::Texture>());
-  ASSERT_TRUE(t->As<ast::type::Texture>()->Is<ast::type::DepthTexture>());
+  ASSERT_TRUE(t->Is<ast::type::DepthTexture>());
   EXPECT_EQ(t->As<ast::type::Texture>()->dim(),
             ast::type::TextureDimension::kCubeArray);
   EXPECT_FALSE(p->has_error());
diff --git a/src/transform/bound_array_accessors_transform.cc b/src/transform/bound_array_accessors_transform.cc
index 86d83ee..f1ecc64 100644
--- a/src/transform/bound_array_accessors_transform.cc
+++ b/src/transform/bound_array_accessors_transform.cc
@@ -213,20 +213,20 @@
   // Scalar constructor we can re-write the value to be within bounds.
   if (auto* c = expr->idx_expr()->As<ast::ScalarConstructorExpression>()) {
     auto* lit = c->literal();
-    if (lit->Is<ast::SintLiteral>()) {
-      int32_t val = lit->As<ast::SintLiteral>()->value();
+    if (auto* sint = lit->As<ast::SintLiteral>()) {
+      int32_t val = sint->value();
       if (val < 0) {
         val = 0;
       } else if (val >= int32_t(size)) {
         val = int32_t(size) - 1;
       }
-      lit->As<ast::SintLiteral>()->set_value(val);
-    } else if (lit->Is<ast::UintLiteral>()) {
-      uint32_t val = lit->As<ast::UintLiteral>()->value();
+      sint->set_value(val);
+    } else if (auto* uint = lit->As<ast::UintLiteral>()) {
+      uint32_t val = uint->value();
       if (val >= size - 1) {
         val = size - 1;
       }
-      lit->As<ast::UintLiteral>()->set_value(val);
+      uint->set_value(val);
     } else {
       error_ = "unknown scalar constructor type for accessor";
       return false;
diff --git a/src/transform/vertex_pulling_transform.cc b/src/transform/vertex_pulling_transform.cc
index 21aa053..49b8ba6 100644
--- a/src/transform/vertex_pulling_transform.cc
+++ b/src/transform/vertex_pulling_transform.cc
@@ -128,11 +128,11 @@
     }
 
     for (auto* d : v->As<ast::DecoratedVariable>()->decorations()) {
-      if (d->Is<ast::BuiltinDecoration>() &&
-          d->As<ast::BuiltinDecoration>()->value() ==
-              ast::Builtin::kVertexIdx) {
-        vertex_index_name_ = v->name();
-        return;
+      if (auto* builtin = d->As<ast::BuiltinDecoration>()) {
+        if (builtin->value() == ast::Builtin::kVertexIdx) {
+          vertex_index_name_ = v->name();
+          return;
+        }
       }
     }
   }
@@ -172,11 +172,11 @@
     }
 
     for (auto* d : v->As<ast::DecoratedVariable>()->decorations()) {
-      if (d->Is<ast::BuiltinDecoration>() &&
-          d->As<ast::BuiltinDecoration>()->value() ==
-              ast::Builtin::kInstanceIdx) {
-        instance_index_name_ = v->name();
-        return;
+      if (auto* builtin = d->As<ast::BuiltinDecoration>()) {
+        if (builtin->value() == ast::Builtin::kInstanceIdx) {
+          instance_index_name_ = v->name();
+          return;
+        }
       }
     }
   }
diff --git a/src/type_determiner.cc b/src/type_determiner.cc
index 6679e20..6b46f9e 100644
--- a/src/type_determiner.cc
+++ b/src/type_determiner.cc
@@ -88,15 +88,13 @@
 bool TypeDeterminer::Determine() {
   for (auto& iter : mod_->types()) {
     auto& type = iter.second;
-    if (!type->Is<ast::type::Texture>() ||
-        !type->Is<ast::type::StorageTexture>()) {
-      continue;
-    }
-    if (!DetermineStorageTextureSubtype(
-            type->As<ast::type::StorageTexture>())) {
-      set_error(Source{}, "unable to determine storage texture subtype for: " +
-                              type->type_name());
-      return false;
+    if (auto* storage = type->As<ast::type::StorageTexture>()) {
+      if (!DetermineStorageTextureSubtype(storage)) {
+        set_error(Source{},
+                  "unable to determine storage texture subtype for: " +
+                      type->type_name());
+        return false;
+      }
     }
   }
 
@@ -180,11 +178,12 @@
 }
 
 bool TypeDeterminer::DetermineVariableStorageClass(ast::Statement* stmt) {
-  if (!stmt->Is<ast::VariableDeclStatement>()) {
+  auto* var_decl = stmt->As<ast::VariableDeclStatement>();
+  if (var_decl == nullptr) {
     return true;
   }
 
-  auto* var = stmt->As<ast::VariableDeclStatement>()->variable();
+  auto* var = var_decl->variable();
   // Nothing to do for const
   if (var->is_const()) {
     return true;
@@ -330,13 +329,12 @@
   auto* res = expr->array()->result_type();
   auto* parent_type = res->UnwrapAll();
   ast::type::Type* ret = nullptr;
-  if (parent_type->Is<ast::type::Array>()) {
-    ret = parent_type->As<ast::type::Array>()->type();
-  } else if (parent_type->Is<ast::type::Vector>()) {
-    ret = parent_type->As<ast::type::Vector>()->type();
-  } else if (parent_type->Is<ast::type::Matrix>()) {
-    auto* m = parent_type->As<ast::type::Matrix>();
-    ret = mod_->create<ast::type::Vector>(m->type(), m->rows());
+  if (auto* arr = parent_type->As<ast::type::Array>()) {
+    ret = arr->type();
+  } else if (auto* vec = parent_type->As<ast::type::Vector>()) {
+    ret = vec->type();
+  } else if (auto* mat = parent_type->As<ast::type::Matrix>()) {
+    ret = mod_->create<ast::type::Vector>(mat->type(), mat->rows());
   } else {
     set_error(expr->source(), "invalid parent type (" +
                                   parent_type->type_name() +
@@ -345,15 +343,15 @@
   }
 
   // If we're extracting from a pointer, we return a pointer.
-  if (res->Is<ast::type::Pointer>()) {
-    ret = mod_->create<ast::type::Pointer>(
-        ret, res->As<ast::type::Pointer>()->storage_class());
-  } else if (parent_type->Is<ast::type::Array>() &&
-             !parent_type->As<ast::type::Array>()->type()->is_scalar()) {
-    // If we extract a non-scalar from an array then we also get a pointer. We
-    // will generate a Function storage class variable to store this
-    // into.
-    ret = mod_->create<ast::type::Pointer>(ret, ast::StorageClass::kFunction);
+  if (auto* ptr = res->As<ast::type::Pointer>()) {
+    ret = mod_->create<ast::type::Pointer>(ret, ptr->storage_class());
+  } else if (auto* arr = parent_type->As<ast::type::Array>()) {
+    if (!arr->type()->is_scalar()) {
+      // If we extract a non-scalar from an array then we also get a pointer. We
+      // will generate a Function storage class variable to store this
+      // into.
+      ret = mod_->create<ast::type::Pointer>(ret, ast::StorageClass::kFunction);
+    }
   }
   expr->set_result_type(ret);
 
@@ -532,9 +530,9 @@
     auto* bool_type = mod_->create<ast::type::Bool>();
 
     auto* param_type = expr->params()[0]->result_type()->UnwrapPtrIfNeeded();
-    if (param_type->Is<ast::type::Vector>()) {
-      expr->func()->set_result_type(mod_->create<ast::type::Vector>(
-          bool_type, param_type->As<ast::type::Vector>()->size()));
+    if (auto* vec = param_type->As<ast::type::Vector>()) {
+      expr->func()->set_result_type(
+          mod_->create<ast::type::Vector>(bool_type, vec->size()));
     } else {
       expr->func()->set_result_type(bool_type);
     }
@@ -662,20 +660,13 @@
       return true;
     }
 
-    if (!texture->Is<ast::type::StorageTexture>() &&
-        !(texture->Is<ast::type::SampledTexture>() ||
-          texture->Is<ast::type::MultisampledTexture>())) {
-      set_error(expr->source(), "invalid texture for " + ident->name());
-      return false;
-    }
-
     ast::type::Type* type = nullptr;
-    if (texture->Is<ast::type::StorageTexture>()) {
-      type = texture->As<ast::type::StorageTexture>()->type();
-    } else if (texture->Is<ast::type::SampledTexture>()) {
-      type = texture->As<ast::type::SampledTexture>()->type();
-    } else if (texture->Is<ast::type::MultisampledTexture>()) {
-      type = texture->As<ast::type::MultisampledTexture>()->type();
+    if (auto* storage = texture->As<ast::type::StorageTexture>()) {
+      type = storage->type();
+    } else if (auto* sampled = texture->As<ast::type::SampledTexture>()) {
+      type = sampled->type();
+    } else if (auto* msampled = texture->As<ast::type::MultisampledTexture>()) {
+      type = msampled->type();
     } else {
       set_error(expr->source(), "unknown texture type for texture sampling");
       return false;
@@ -1030,8 +1021,8 @@
   auto* data_type = res->UnwrapPtrIfNeeded()->UnwrapIfNeeded();
 
   ast::type::Type* ret = nullptr;
-  if (data_type->Is<ast::type::Struct>()) {
-    auto* strct = data_type->As<ast::type::Struct>()->impl();
+  if (auto* ty = data_type->As<ast::type::Struct>()) {
+    auto* strct = ty->impl();
     auto name = expr->member()->name();
 
     for (auto* member : strct->members()) {
@@ -1047,21 +1038,17 @@
     }
 
     // If we're extracting from a pointer, we return a pointer.
-    if (res->Is<ast::type::Pointer>()) {
-      ret = mod_->create<ast::type::Pointer>(
-          ret, res->As<ast::type::Pointer>()->storage_class());
+    if (auto* ptr = res->As<ast::type::Pointer>()) {
+      ret = mod_->create<ast::type::Pointer>(ret, ptr->storage_class());
     }
-  } else if (data_type->Is<ast::type::Vector>()) {
-    auto* vec = data_type->As<ast::type::Vector>();
-
+  } else if (auto* vec = data_type->As<ast::type::Vector>()) {
     auto size = expr->member()->name().size();
     if (size == 1) {
       // A single element swizzle is just the type of the vector.
       ret = vec->type();
       // If we're extracting from a pointer, we return a pointer.
-      if (res->Is<ast::type::Pointer>()) {
-        ret = mod_->create<ast::type::Pointer>(
-            ret, res->As<ast::type::Pointer>()->storage_class());
+      if (auto* ptr = res->As<ast::type::Pointer>()) {
+        ret = mod_->create<ast::type::Pointer>(ret, ptr->storage_class());
       }
     } else {
       // The vector will have a number of components equal to the length of the
@@ -1100,9 +1087,9 @@
       expr->IsLessThanEqual() || expr->IsGreaterThanEqual()) {
     auto* bool_type = mod_->create<ast::type::Bool>();
     auto* param_type = expr->lhs()->result_type()->UnwrapPtrIfNeeded();
-    if (param_type->Is<ast::type::Vector>()) {
-      expr->set_result_type(mod_->create<ast::type::Vector>(
-          bool_type, param_type->As<ast::type::Vector>()->size()));
+    if (auto* vec = param_type->As<ast::type::Vector>()) {
+      expr->set_result_type(
+          mod_->create<ast::type::Vector>(bool_type, vec->size()));
     } else {
       expr->set_result_type(bool_type);
     }
@@ -1114,36 +1101,31 @@
 
     // Note, the ordering here matters. The later checks depend on the prior
     // checks having been done.
-    if (lhs_type->Is<ast::type::Matrix>() &&
-        rhs_type->Is<ast::type::Matrix>()) {
+    auto* lhs_mat = lhs_type->As<ast::type::Matrix>();
+    auto* rhs_mat = rhs_type->As<ast::type::Matrix>();
+    auto* lhs_vec = lhs_type->As<ast::type::Vector>();
+    auto* rhs_vec = rhs_type->As<ast::type::Vector>();
+    if (lhs_mat && rhs_mat) {
       expr->set_result_type(mod_->create<ast::type::Matrix>(
-          lhs_type->As<ast::type::Matrix>()->type(),
-          lhs_type->As<ast::type::Matrix>()->rows(),
-          rhs_type->As<ast::type::Matrix>()->columns()));
-
-    } else if (lhs_type->Is<ast::type::Matrix>() &&
-               rhs_type->Is<ast::type::Vector>()) {
-      auto* mat = lhs_type->As<ast::type::Matrix>();
+          lhs_mat->type(), lhs_mat->rows(), rhs_mat->columns()));
+    } else if (lhs_mat && rhs_vec) {
       expr->set_result_type(
-          mod_->create<ast::type::Vector>(mat->type(), mat->rows()));
-    } else if (lhs_type->Is<ast::type::Vector>() &&
-               rhs_type->Is<ast::type::Matrix>()) {
-      auto* mat = rhs_type->As<ast::type::Matrix>();
+          mod_->create<ast::type::Vector>(lhs_mat->type(), lhs_mat->rows()));
+    } else if (lhs_vec && rhs_mat) {
       expr->set_result_type(
-          mod_->create<ast::type::Vector>(mat->type(), mat->columns()));
-    } else if (lhs_type->Is<ast::type::Matrix>()) {
+          mod_->create<ast::type::Vector>(rhs_mat->type(), rhs_mat->columns()));
+    } else if (lhs_mat) {
       // matrix * scalar
       expr->set_result_type(lhs_type);
-    } else if (rhs_type->Is<ast::type::Matrix>()) {
+    } else if (rhs_mat) {
       // scalar * matrix
       expr->set_result_type(rhs_type);
-    } else if (lhs_type->Is<ast::type::Vector>() &&
-               rhs_type->Is<ast::type::Vector>()) {
+    } else if (lhs_vec && rhs_vec) {
       expr->set_result_type(lhs_type);
-    } else if (lhs_type->Is<ast::type::Vector>()) {
+    } else if (lhs_vec) {
       // Vector * scalar
       expr->set_result_type(lhs_type);
-    } else if (rhs_type->Is<ast::type::Vector>()) {
+    } else if (rhs_vec) {
       // Scalar * vector
       expr->set_result_type(rhs_type);
     } else {
diff --git a/src/validator/validator_impl.cc b/src/validator/validator_impl.cc
index 237776b..b6fe903 100644
--- a/src/validator/validator_impl.cc
+++ b/src/validator/validator_impl.cc
@@ -85,11 +85,9 @@
 bool ValidatorImpl::ValidateConstructedTypes(
     const std::vector<ast::type::Type*>& constructed_types) {
   for (auto* const ct : constructed_types) {
-    if (ct->Is<ast::type::Struct>()) {
-      auto* st = ct->As<ast::type::Struct>();
+    if (auto* st = ct->As<ast::type::Struct>()) {
       for (auto* member : st->impl()->members()) {
-        if (member->type()->UnwrapAll()->Is<ast::type::Array>()) {
-          auto* r = member->type()->UnwrapAll()->As<ast::type::Array>();
+        if (auto* r = member->type()->UnwrapAll()->As<ast::type::Array>()) {
           if (r->IsRuntimeArray()) {
             if (member != st->impl()->members().back()) {
               add_error(member->source(), "v-0015",
@@ -265,12 +263,9 @@
     return false;
   }
   variable_stack_.set(name, decl->variable());
-  if (decl->variable()->type()->UnwrapAll()->Is<ast::type::Array>()) {
-    if (decl->variable()
-            ->type()
-            ->UnwrapAll()
-            ->As<ast::type::Array>()
-            ->IsRuntimeArray()) {
+  if (auto* arr =
+          decl->variable()->type()->UnwrapAll()->As<ast::type::Array>()) {
+    if (arr->IsRuntimeArray()) {
       add_error(decl->source(), "v-0015",
                 "runtime arrays may only appear as the last "
                 "member of a struct: '" +
@@ -317,7 +312,7 @@
   }
 
   auto* cond_type = s->condition()->result_type()->UnwrapAll();
-  if (!(cond_type->Is<ast::type::I32>() || cond_type->Is<ast::type::U32>())) {
+  if (!cond_type->is_integer_scalar()) {
     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 2979bb9..2b66d3f 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -219,13 +219,11 @@
                                         const ast::type::Type* ty) {
   make_indent(out);
 
-  if (ty->Is<ast::type::Alias>()) {
-    auto* alias = ty->As<ast::type::Alias>();
+  if (auto* alias = ty->As<ast::type::Alias>()) {
     // HLSL typedef is for intrinsic types only. For an alias'd struct,
     // generate a secondary struct with the new name.
-    if (alias->type()->Is<ast::type::Struct>()) {
-      if (!EmitStructType(out, alias->type()->As<ast::type::Struct>(),
-                          alias->name())) {
+    if (auto* str = alias->type()->As<ast::type::Struct>()) {
+      if (!EmitStructType(out, str, alias->name())) {
         return false;
       }
       return true;
@@ -235,8 +233,7 @@
       return false;
     }
     out << " " << namer_.NameFor(alias->name()) << ";" << std::endl;
-  } else if (ty->Is<ast::type::Struct>()) {
-    auto* str = ty->As<ast::type::Struct>();
+  } else if (auto* str = ty->As<ast::type::Struct>()) {
     if (!EmitStructType(out, str, str->name())) {
       return false;
     }
@@ -272,9 +269,7 @@
 bool GeneratorImpl::EmitBitcast(std::ostream& pre,
                                 std::ostream& out,
                                 ast::BitcastExpression* expr) {
-  if (!expr->type()->Is<ast::type::F32>() &&
-      !expr->type()->Is<ast::type::I32>() &&
-      !expr->type()->Is<ast::type::U32>()) {
+  if (!expr->type()->is_integer_scalar() && !expr->type()->is_float_scalar()) {
     error_ = "Unable to do bitcast to type " + expr->type()->type_name();
     return false;
   }
@@ -1005,11 +1000,14 @@
 }
 
 bool GeneratorImpl::global_is_in_struct(ast::Variable* var) const {
-  return var->Is<ast::DecoratedVariable>() &&
-         (var->As<ast::DecoratedVariable>()->HasLocationDecoration() ||
-          var->As<ast::DecoratedVariable>()->HasBuiltinDecoration()) &&
-         (var->storage_class() == ast::StorageClass::kInput ||
-          var->storage_class() == ast::StorageClass::kOutput);
+  if (auto* decorated = var->As<ast::DecoratedVariable>()) {
+    if (decorated->HasLocationDecoration() ||
+        decorated->HasBuiltinDecoration()) {
+      return var->storage_class() == ast::StorageClass::kInput ||
+             var->storage_class() == ast::StorageClass::kOutput;
+    }
+  }
+  return false;
 }
 
 bool GeneratorImpl::EmitIdentifier(std::ostream&,
@@ -1298,9 +1296,7 @@
     emitted_globals.insert(var->name());
 
     auto* type = var->type()->UnwrapIfNeeded();
-    if (type->Is<ast::type::Struct>()) {
-      auto* strct = type->As<ast::type::Struct>();
-
+    if (auto* strct = type->As<ast::type::Struct>()) {
       out << "ConstantBuffer<" << strct->name() << "> " << var->name()
           << " : register(b" << binding->value() << ");" << std::endl;
     } else {
@@ -1340,11 +1336,11 @@
     }
     emitted_globals.insert(var->name());
 
-    if (!var->type()->Is<ast::type::AccessControl>()) {
+    auto* ac = var->type()->As<ast::type::AccessControl>();
+    if (ac == nullptr) {
       error_ = "access control type required for storage buffer";
       return false;
     }
-    auto* ac = var->type()->As<ast::type::AccessControl>();
 
     if (ac->IsReadWrite()) {
       out << "RW";
@@ -1538,14 +1534,14 @@
 }
 
 bool GeneratorImpl::EmitLiteral(std::ostream& out, ast::Literal* lit) {
-  if (lit->Is<ast::BoolLiteral>()) {
-    out << (lit->As<ast::BoolLiteral>()->IsTrue() ? "true" : "false");
-  } else if (lit->Is<ast::FloatLiteral>()) {
-    out << FloatToString(lit->As<ast::FloatLiteral>()->value()) << "f";
-  } else if (lit->Is<ast::SintLiteral>()) {
-    out << lit->As<ast::SintLiteral>()->value();
-  } else if (lit->Is<ast::UintLiteral>()) {
-    out << lit->As<ast::UintLiteral>()->value() << "u";
+  if (auto* l = lit->As<ast::BoolLiteral>()) {
+    out << (l->IsTrue() ? "true" : "false");
+  } else if (auto* fl = lit->As<ast::FloatLiteral>()) {
+    out << FloatToString(fl->value()) << "f";
+  } else if (auto* sl = lit->As<ast::SintLiteral>()) {
+    out << sl->value();
+  } else if (auto* ul = lit->As<ast::UintLiteral>()) {
+    out << ul->value() << "u";
   } else {
     error_ = "unknown literal type";
     return false;
@@ -1562,10 +1558,9 @@
     out << "0";
   } else if (type->Is<ast::type::U32>()) {
     out << "0u";
-  } else if (type->Is<ast::type::Vector>()) {
-    return EmitZeroValue(out, type->As<ast::type::Vector>()->type());
-  } else if (type->Is<ast::type::Matrix>()) {
-    auto* mat = type->As<ast::type::Matrix>();
+  } else if (auto* vec = type->As<ast::type::Vector>()) {
+    return EmitZeroValue(out, vec->type());
+  } else if (auto* mat = type->As<ast::type::Matrix>()) {
     for (uint32_t i = 0; i < (mat->rows() * mat->columns()); i++) {
       if (i != 0) {
         out << ", ";
@@ -1630,31 +1625,32 @@
   for (auto* s : *(stmt->body())) {
     // If we have a continuing block we've already emitted the variable
     // declaration before the loop, so treat it as an assignment.
-    auto* decl = s->As<ast::VariableDeclStatement>();
-    if (decl != nullptr && stmt->has_continuing()) {
-      make_indent(out);
+    if (auto* decl = s->As<ast::VariableDeclStatement>()) {
+      if (stmt->has_continuing()) {
+        make_indent(out);
 
-      auto* var = decl->variable();
+        auto* var = decl->variable();
 
-      std::ostringstream pre;
-      std::ostringstream constructor_out;
-      if (var->constructor() != nullptr) {
-        if (!EmitExpression(pre, constructor_out, var->constructor())) {
-          return false;
+        std::ostringstream pre;
+        std::ostringstream constructor_out;
+        if (var->constructor() != nullptr) {
+          if (!EmitExpression(pre, constructor_out, var->constructor())) {
+            return false;
+          }
         }
-      }
-      out << pre.str();
+        out << pre.str();
 
-      out << var->name() << " = ";
-      if (var->constructor() != nullptr) {
-        out << constructor_out.str();
-      } else {
-        if (!EmitZeroValue(out, var->type())) {
-          return false;
+        out << var->name() << " = ";
+        if (var->constructor() != nullptr) {
+          out << constructor_out.str();
+        } else {
+          if (!EmitZeroValue(out, var->type())) {
+            return false;
+          }
         }
+        out << ";" << std::endl;
+        continue;
       }
-      out << ";" << std::endl;
-      continue;
     }
 
     if (!EmitStatement(out, s)) {
@@ -1692,8 +1688,8 @@
     first = false;
     if (auto* mem = expr->As<ast::MemberAccessorExpression>()) {
       auto* res_type = mem->structure()->result_type()->UnwrapAll();
-      if (res_type->Is<ast::type::Struct>()) {
-        auto* str_type = res_type->As<ast::type::Struct>()->impl();
+      if (auto* str = res_type->As<ast::type::Struct>()) {
+        auto* str_type = str->impl();
         auto* str_member = str_type->get_member(mem->member()->name());
 
         if (!str_member->has_offset_decoration()) {
@@ -1728,15 +1724,14 @@
       auto* ary_type = ary->array()->result_type()->UnwrapAll();
 
       out << "(";
-      if (ary_type->Is<ast::type::Array>()) {
-        out << ary_type->As<ast::type::Array>()->array_stride();
+      if (auto* arr = ary_type->As<ast::type::Array>()) {
+        out << arr->array_stride();
       } else if (ary_type->Is<ast::type::Vector>()) {
         // TODO(dsinclair): This is a hack. Our vectors can only be f32, i32
         // 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->Is<ast::type::Matrix>()) {
-        auto* mat = ary_type->As<ast::type::Matrix>();
+      } else if (auto* mat = ary_type->As<ast::type::Matrix>()) {
         if (mat->columns() == 2) {
           out << "8";
         } else {
@@ -1777,12 +1772,10 @@
   bool is_store = rhs != nullptr;
 
   std::string access_method = is_store ? "Store" : "Load";
-  if (result_type->Is<ast::type::Vector>()) {
-    access_method +=
-        std::to_string(result_type->As<ast::type::Vector>()->size());
-  } else if (result_type->Is<ast::type::Matrix>()) {
-    access_method +=
-        std::to_string(result_type->As<ast::type::Matrix>()->rows());
+  if (auto* vec = result_type->As<ast::type::Vector>()) {
+    access_method += std::to_string(vec->size());
+  } else if (auto* mat = result_type->As<ast::type::Matrix>()) {
+    access_method += std::to_string(mat->rows());
   }
 
   // If we aren't storing then we need to put in the outer cast.
@@ -1808,9 +1801,7 @@
     return false;
   }
 
-  if (result_type->Is<ast::type::Matrix>()) {
-    auto* mat = result_type->As<ast::type::Matrix>();
-
+  if (auto* mat = result_type->As<ast::type::Matrix>()) {
     // TODO(dsinclair): This is assuming 4 byte elements. Will need to be fixed
     // if we get matrixes of f16 or f64.
     uint32_t stride = mat->rows() == 2 ? 8 : 16;
@@ -2041,24 +2032,21 @@
 bool GeneratorImpl::EmitType(std::ostream& out,
                              ast::type::Type* type,
                              const std::string& name) {
-  if (type->Is<ast::type::Alias>()) {
-    auto* alias = type->As<ast::type::Alias>();
+  if (auto* alias = type->As<ast::type::Alias>()) {
     out << namer_.NameFor(alias->name());
-  } else if (type->Is<ast::type::Array>()) {
-    auto* ary = type->As<ast::type::Array>();
-
+  } else if (auto* ary = type->As<ast::type::Array>()) {
     ast::type::Type* base_type = ary;
     std::vector<uint32_t> sizes;
-    while (base_type->Is<ast::type::Array>()) {
-      if (base_type->As<ast::type::Array>()->IsRuntimeArray()) {
+    while (auto* arr = base_type->As<ast::type::Array>()) {
+      if (arr->IsRuntimeArray()) {
         // TODO(dsinclair): Support runtime arrays
         // https://bugs.chromium.org/p/tint/issues/detail?id=185
         error_ = "runtime array not supported yet.";
         return false;
       } else {
-        sizes.push_back(base_type->As<ast::type::Array>()->size());
+        sizes.push_back(arr->size());
       }
-      base_type = base_type->As<ast::type::Array>()->type();
+      base_type = arr->type();
     }
     if (!EmitType(out, base_type, "")) {
       return false;
@@ -2075,8 +2063,7 @@
     out << "float";
   } else if (type->Is<ast::type::I32>()) {
     out << "int";
-  } else if (type->Is<ast::type::Matrix>()) {
-    auto* mat = type->As<ast::type::Matrix>();
+  } else if (auto* mat = type->As<ast::type::Matrix>()) {
     if (!EmitType(out, mat->type(), "")) {
       return false;
     }
@@ -2086,17 +2073,15 @@
     // https://bugs.chromium.org/p/tint/issues/detail?id=183
     error_ = "pointers not supported in HLSL";
     return false;
-  } else if (type->Is<ast::type::Sampler>()) {
-    auto* sampler = type->As<ast::type::Sampler>();
+  } else if (auto* sampler = type->As<ast::type::Sampler>()) {
     out << "Sampler";
     if (sampler->IsComparison()) {
       out << "Comparison";
     }
     out << "State";
-  } else if (type->Is<ast::type::Struct>()) {
-    out << type->As<ast::type::Struct>()->name();
-  } else if (type->Is<ast::type::Texture>()) {
-    auto* tex = type->As<ast::type::Texture>();
+  } else if (auto* str = type->As<ast::type::Struct>()) {
+    out << str->name();
+  } else if (auto* tex = type->As<ast::type::Texture>()) {
     if (tex->Is<ast::type::StorageTexture>()) {
       out << "RW";
     }
@@ -2131,8 +2116,7 @@
 
   } else if (type->Is<ast::type::U32>()) {
     out << "uint";
-  } else if (type->Is<ast::type::Vector>()) {
-    auto* vec = type->As<ast::type::Vector>();
+  } else if (auto* vec = type->As<ast::type::Vector>()) {
     auto size = vec->size();
     if (vec->type()->Is<ast::type::F32>() && size >= 1 && size <= 4) {
       out << "float" << size;
@@ -2250,8 +2234,8 @@
                                              const ast::Variable* var) {
   make_indent(out);
 
-  if (var->Is<ast::DecoratedVariable>() &&
-      !var->As<ast::DecoratedVariable>()->HasConstantIdDecoration()) {
+  auto* decorated = var->As<ast::DecoratedVariable>();
+  if (decorated != nullptr && !decorated->HasConstantIdDecoration()) {
     error_ = "Decorated const values not valid";
     return false;
   }
@@ -2269,9 +2253,8 @@
     out << pre.str();
   }
 
-  if (var->Is<ast::DecoratedVariable>() &&
-      var->As<ast::DecoratedVariable>()->HasConstantIdDecoration()) {
-    auto const_id = var->As<ast::DecoratedVariable>()->constant_id();
+  if (decorated != nullptr && decorated->HasConstantIdDecoration()) {
+    auto const_id = decorated->constant_id();
 
     out << "#ifndef WGSL_SPEC_CONSTANT_" << const_id << std::endl;
 
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index 76dd997..1161be7 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -186,11 +186,10 @@
 }
 
 uint32_t GeneratorImpl::calculate_alignment_size(ast::type::Type* type) {
-  if (type->Is<ast::type::Alias>()) {
-    return calculate_alignment_size(type->As<ast::type::Alias>()->type());
+  if (auto* alias = type->As<ast::type::Alias>()) {
+    return calculate_alignment_size(alias->type());
   }
-  if (type->Is<ast::type::Array>()) {
-    auto* ary = type->As<ast::type::Array>();
+  if (auto* ary = type->As<ast::type::Array>()) {
     // TODO(dsinclair): Handle array stride and adjust for alignment.
     uint32_t type_size = calculate_alignment_size(ary->type());
     return ary->size() * type_size;
@@ -205,15 +204,14 @@
       type->Is<ast::type::U32>()) {
     return 4;
   }
-  if (type->Is<ast::type::Matrix>()) {
-    auto* mat = type->As<ast::type::Matrix>();
+  if (auto* mat = type->As<ast::type::Matrix>()) {
     // TODO(dsinclair): Handle MatrixStride
     // https://github.com/gpuweb/gpuweb/issues/773
     uint32_t type_size = calculate_alignment_size(mat->type());
     return mat->rows() * mat->columns() * type_size;
   }
-  if (type->Is<ast::type::Struct>()) {
-    auto* stct = type->As<ast::type::Struct>()->impl();
+  if (auto* stct_ty = type->As<ast::type::Struct>()) {
+    auto* stct = stct_ty->impl();
     uint32_t count = 0;
     uint32_t largest_alignment = 0;
     // Offset decorations in WGSL must be in increasing order.
@@ -227,12 +225,11 @@
       if (align == 0) {
         return 0;
       }
-      if (!mem->type()->Is<ast::type::Struct>()) {
-        largest_alignment = std::max(largest_alignment, align);
+      if (auto* str = mem->type()->As<ast::type::Struct>()) {
+        largest_alignment =
+            std::max(largest_alignment, calculate_largest_alignment(str));
       } else {
-        largest_alignment = std::max(
-            largest_alignment,
-            calculate_largest_alignment(mem->type()->As<ast::type::Struct>()));
+        largest_alignment = std::max(largest_alignment, align);
       }
 
       // Round up to the alignment size
@@ -243,8 +240,7 @@
     count = adjust_for_alignment(count, largest_alignment);
     return count;
   }
-  if (type->Is<ast::type::Vector>()) {
-    auto* vec = type->As<ast::type::Vector>();
+  if (auto* vec = type->As<ast::type::Vector>()) {
     uint32_t type_size = calculate_alignment_size(vec->type());
     if (vec->size() == 2) {
       return 2 * type_size;
@@ -257,16 +253,14 @@
 bool GeneratorImpl::EmitConstructedType(const ast::type::Type* ty) {
   make_indent();
 
-  if (ty->Is<ast::type::Alias>()) {
-    auto* alias = ty->As<ast::type::Alias>();
-
+  if (auto* alias = ty->As<ast::type::Alias>()) {
     out_ << "typedef ";
     if (!EmitType(alias->type(), "")) {
       return false;
     }
     out_ << " " << namer_.NameFor(alias->name()) << ";" << std::endl;
-  } else if (ty->Is<ast::type::Struct>()) {
-    if (!EmitStructType(ty->As<ast::type::Struct>())) {
+  } else if (auto* str = ty->As<ast::type::Struct>()) {
+    if (!EmitStructType(str)) {
       return false;
     }
   } else {
@@ -940,17 +934,17 @@
     out_ << "0";
   } else if (type->Is<ast::type::U32>()) {
     out_ << "0u";
-  } else if (type->Is<ast::type::Vector>()) {
-    return EmitZeroValue(type->As<ast::type::Vector>()->type());
-  } else if (type->Is<ast::type::Matrix>()) {
-    return EmitZeroValue(type->As<ast::type::Matrix>()->type());
-  } else if (type->Is<ast::type::Array>()) {
+  } else if (auto* vec = type->As<ast::type::Vector>()) {
+    return EmitZeroValue(vec->type());
+  } else if (auto* mat = type->As<ast::type::Matrix>()) {
+    return EmitZeroValue(mat->type());
+  } else if (auto* arr = type->As<ast::type::Array>()) {
     out_ << "{";
-    if (!EmitZeroValue(type->As<ast::type::Array>()->type())) {
+    if (!EmitZeroValue(arr->type())) {
       return false;
     }
     out_ << "}";
-  } else if (type->Is<ast::type::Struct>()) {
+  } else if (type->As<ast::type::Struct>()) {
     out_ << "{}";
   } else {
     error_ = "Invalid type for zero emission: " + type->type_name();
@@ -965,14 +959,14 @@
 }
 
 bool GeneratorImpl::EmitLiteral(ast::Literal* lit) {
-  if (lit->Is<ast::BoolLiteral>()) {
-    out_ << (lit->As<ast::BoolLiteral>()->IsTrue() ? "true" : "false");
-  } else if (lit->Is<ast::FloatLiteral>()) {
-    out_ << FloatToString(lit->As<ast::FloatLiteral>()->value()) << "f";
-  } else if (lit->Is<ast::SintLiteral>()) {
-    out_ << lit->As<ast::SintLiteral>()->value();
-  } else if (lit->Is<ast::UintLiteral>()) {
-    out_ << lit->As<ast::UintLiteral>()->value() << "u";
+  if (auto* l = lit->As<ast::BoolLiteral>()) {
+    out_ << (l->IsTrue() ? "true" : "false");
+  } else if (auto* fl = lit->As<ast::FloatLiteral>()) {
+    out_ << FloatToString(fl->value()) << "f";
+  } else if (auto* sl = lit->As<ast::SintLiteral>()) {
+    out_ << sl->value();
+  } else if (auto* ul = lit->As<ast::UintLiteral>()) {
+    out_ << ul->value() << "u";
   } else {
     error_ = "unknown literal type";
     return false;
@@ -1286,11 +1280,11 @@
     }
     first = false;
 
-    if (!var->type()->Is<ast::type::AccessControl>()) {
+    auto* ac = var->type()->As<ast::type::AccessControl>();
+    if (ac == nullptr) {
       error_ = "invalid type for storage buffer, expected access control";
       return false;
     }
-    auto* ac = var->type()->As<ast::type::AccessControl>();
     if (ac->IsReadOnly()) {
       out_ << "const ";
     }
@@ -1447,11 +1441,11 @@
     auto* binding = data.second.binding;
     // auto* set = data.second.set;
 
-    if (!var->type()->Is<ast::type::AccessControl>()) {
+    auto* ac = var->type()->As<ast::type::AccessControl>();
+    if (ac == nullptr) {
       error_ = "invalid type for storage buffer, expected access control";
       return false;
     }
-    auto* ac = var->type()->As<ast::type::AccessControl>();
     if (ac->IsReadOnly()) {
       out_ << "const ";
     }
@@ -1490,14 +1484,13 @@
 }
 
 bool GeneratorImpl::global_is_in_struct(ast::Variable* var) const {
+  auto* decorated = var->As<ast::DecoratedVariable>();
   bool in_or_out_struct_has_location =
-      var->Is<ast::DecoratedVariable>() &&
-      var->As<ast::DecoratedVariable>()->HasLocationDecoration() &&
+      decorated != nullptr && decorated->HasLocationDecoration() &&
       (var->storage_class() == ast::StorageClass::kInput ||
        var->storage_class() == ast::StorageClass::kOutput);
   bool in_struct_has_builtin =
-      var->Is<ast::DecoratedVariable>() &&
-      var->As<ast::DecoratedVariable>()->HasBuiltinDecoration() &&
+      decorated != nullptr && decorated->HasBuiltinDecoration() &&
       var->storage_class() == ast::StorageClass::kOutput;
   return in_or_out_struct_has_location || in_struct_has_builtin;
 }
@@ -1793,21 +1786,18 @@
 }
 
 bool GeneratorImpl::EmitType(ast::type::Type* type, const std::string& name) {
-  if (type->Is<ast::type::Alias>()) {
-    auto* alias = type->As<ast::type::Alias>();
+  if (auto* alias = type->As<ast::type::Alias>()) {
     out_ << namer_.NameFor(alias->name());
-  } else if (type->Is<ast::type::Array>()) {
-    auto* ary = type->As<ast::type::Array>();
-
+  } else if (auto* ary = type->As<ast::type::Array>()) {
     ast::type::Type* base_type = ary;
     std::vector<uint32_t> sizes;
-    while (base_type->Is<ast::type::Array>()) {
-      if (base_type->As<ast::type::Array>()->IsRuntimeArray()) {
+    while (auto* arr = base_type->As<ast::type::Array>()) {
+      if (arr->IsRuntimeArray()) {
         sizes.push_back(1);
       } else {
-        sizes.push_back(base_type->As<ast::type::Array>()->size());
+        sizes.push_back(arr->size());
       }
-      base_type = base_type->As<ast::type::Array>()->type();
+      base_type = arr->type();
     }
     if (!EmitType(base_type, "")) {
       return false;
@@ -1824,14 +1814,12 @@
     out_ << "float";
   } else if (type->Is<ast::type::I32>()) {
     out_ << "int";
-  } else if (type->Is<ast::type::Matrix>()) {
-    auto* mat = type->As<ast::type::Matrix>();
+  } else if (auto* mat = type->As<ast::type::Matrix>()) {
     if (!EmitType(mat->type(), "")) {
       return false;
     }
     out_ << mat->columns() << "x" << mat->rows();
-  } else if (type->Is<ast::type::Pointer>()) {
-    auto* ptr = type->As<ast::type::Pointer>();
+  } else if (auto* ptr = type->As<ast::type::Pointer>()) {
     // TODO(dsinclair): Storage class?
     if (!EmitType(ptr->type(), "")) {
       return false;
@@ -1839,13 +1827,11 @@
     out_ << "*";
   } else if (type->Is<ast::type::Sampler>()) {
     out_ << "sampler";
-  } else if (type->Is<ast::type::Struct>()) {
+  } else if (auto* str = type->As<ast::type::Struct>()) {
     // The struct type emits as just the name. The declaration would be emitted
     // as part of emitting the constructed types.
-    out_ << type->As<ast::type::Struct>()->name();
-  } else if (type->Is<ast::type::Texture>()) {
-    auto* tex = type->As<ast::type::Texture>();
-
+    out_ << str->name();
+  } else if (auto* tex = type->As<ast::type::Texture>()) {
     if (tex->Is<ast::type::DepthTexture>()) {
       out_ << "depth";
     } else {
@@ -1884,8 +1870,7 @@
     out_ << "<";
     if (tex->Is<ast::type::DepthTexture>()) {
       out_ << "float, access::sample";
-    } else if (tex->Is<ast::type::StorageTexture>()) {
-      auto* storage = tex->As<ast::type::StorageTexture>();
+    } else if (auto* storage = tex->As<ast::type::StorageTexture>()) {
       if (!EmitType(storage->type(), "")) {
         return false;
       }
@@ -1898,13 +1883,13 @@
         error_ = "Invalid access control for storage texture";
         return false;
       }
-    } else if (tex->Is<ast::type::MultisampledTexture>()) {
-      if (!EmitType(tex->As<ast::type::MultisampledTexture>()->type(), "")) {
+    } else if (auto* ms = tex->As<ast::type::MultisampledTexture>()) {
+      if (!EmitType(ms->type(), "")) {
         return false;
       }
       out_ << ", access::sample";
-    } else if (tex->Is<ast::type::SampledTexture>()) {
-      if (!EmitType(tex->As<ast::type::SampledTexture>()->type(), "")) {
+    } else if (auto* sampled = tex->As<ast::type::SampledTexture>()) {
+      if (!EmitType(sampled->type(), "")) {
         return false;
       }
       out_ << ", access::sample";
@@ -1916,8 +1901,7 @@
 
   } else if (type->Is<ast::type::U32>()) {
     out_ << "uint";
-  } else if (type->Is<ast::type::Vector>()) {
-    auto* vec = type->As<ast::type::Vector>();
+  } else if (auto* vec = type->As<ast::type::Vector>()) {
     if (!EmitType(vec->type(), "")) {
       return false;
     }
@@ -2044,8 +2028,8 @@
 bool GeneratorImpl::EmitProgramConstVariable(const ast::Variable* var) {
   make_indent();
 
-  if (var->Is<ast::DecoratedVariable>() &&
-      !var->As<ast::DecoratedVariable>()->HasConstantIdDecoration()) {
+  auto* decorated = var->As<ast::DecoratedVariable>();
+  if (decorated != nullptr && !decorated->HasConstantIdDecoration()) {
     error_ = "Decorated const values not valid";
     return false;
   }
@@ -2062,10 +2046,8 @@
     out_ << " " << var->name();
   }
 
-  if (var->Is<ast::DecoratedVariable>() &&
-      var->As<ast::DecoratedVariable>()->HasConstantIdDecoration()) {
-    out_ << " [[function_constant("
-         << var->As<ast::DecoratedVariable>()->constant_id() << ")]]";
+  if (decorated != nullptr && decorated->HasConstantIdDecoration()) {
+    out_ << " [[function_constant(" << decorated->constant_id() << ")]]";
   } else if (var->constructor() != nullptr) {
     out_ << " = ";
     if (!EmitExpression(var->constructor())) {
diff --git a/src/writer/pack_coord_arrayidx.cc b/src/writer/pack_coord_arrayidx.cc
index 051f0a9..ec6e770 100644
--- a/src/writer/pack_coord_arrayidx.cc
+++ b/src/writer/pack_coord_arrayidx.cc
@@ -26,14 +26,12 @@
 namespace {
 
 ast::TypeConstructorExpression* AsVectorConstructor(ast::Expression* expr) {
-  auto* type_constructor = expr->As<ast::TypeConstructorExpression>();
-  if (type_constructor == nullptr) {
-    return nullptr;
+  if (auto* constructor = expr->As<ast::TypeConstructorExpression>()) {
+    if (constructor->type()->Is<ast::type::Vector>()) {
+      return constructor;
+    }
   }
-  if (!type_constructor->type()->Is<ast::type::Vector>()) {
-    return nullptr;
-  }
-  return type_constructor;
+  return nullptr;
 }
 
 }  // namespace
@@ -44,8 +42,7 @@
     std::function<bool(ast::TypeConstructorExpression*)> callback) {
   uint32_t packed_size;
   ast::type::Type* packed_el_ty;  // Currenly must be f32.
-  if (coords->result_type()->Is<ast::type::Vector>()) {
-    auto* vec = coords->result_type()->As<ast::type::Vector>();
+  if (auto* vec = coords->result_type()->As<ast::type::Vector>()) {
     packed_size = vec->size() + 1;
     packed_el_ty = vec->type();
   } else {
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index 1527776..04fae91 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -152,11 +152,10 @@
 /// @param type the given type, which must not be null
 /// @returns the nested matrix type, or nullptr if none
 ast::type::Matrix* GetNestedMatrixType(ast::type::Type* type) {
-  while (type->Is<ast::type::Array>()) {
-    type = type->As<ast::type::Array>()->type();
+  while (auto* arr = type->As<ast::type::Array>()) {
+    type = arr->type();
   }
-  return type->Is<ast::type::Matrix>() ? type->As<ast::type::Matrix>()
-                                       : nullptr;
+  return type->As<ast::type::Matrix>();
 }
 
 uint32_t intrinsic_to_glsl_method(ast::type::Type* type,
@@ -721,10 +720,10 @@
                      Operand::Int(ConvertStorageClass(sc))};
   if (var->has_constructor()) {
     ops.push_back(Operand::Int(init_id));
-  } else if (type->Is<ast::type::Texture>()) {
+  } else if (auto* tex = type->As<ast::type::Texture>()) {
     // Decorate storage texture variables with NonRead/Writeable if needed.
-    if (type->Is<ast::type::StorageTexture>()) {
-      switch (type->As<ast::type::StorageTexture>()->access()) {
+    if (auto* storage = tex->As<ast::type::StorageTexture>()) {
+      switch (storage->access()) {
         case ast::AccessControl::kWriteOnly:
           push_annot(
               spv::Op::OpDecorate,
@@ -747,8 +746,8 @@
     //    one
     // 2- If we don't have a constructor and we're an Output or Private variable
     //    then WGSL requires an initializer.
-    if (var->Is<ast::DecoratedVariable>() &&
-        var->As<ast::DecoratedVariable>()->HasConstantIdDecoration()) {
+    auto* decorated = var->As<ast::DecoratedVariable>();
+    if (decorated != nullptr && decorated->HasConstantIdDecoration()) {
       if (type->Is<ast::type::F32>()) {
         ast::FloatLiteral l(type, 0.0f);
         init_id = GenerateLiteralIfNeeded(var, &l);
@@ -1197,30 +1196,25 @@
       return false;
     }
 
-    if (result_type->Is<ast::type::Vector>() &&
-        !e->Is<ast::ScalarConstructorExpression>()) {
+    auto* sc = e->As<ast::ScalarConstructorExpression>();
+    if (result_type->Is<ast::type::Vector>() && sc == nullptr) {
       return false;
     }
 
     // This should all be handled by |is_constructor_const| call above
-    if (!e->Is<ast::ScalarConstructorExpression>()) {
+    if (sc == nullptr) {
       continue;
     }
 
-    auto* sc = e->As<ast::ScalarConstructorExpression>();
     ast::type::Type* subtype = result_type->UnwrapAll();
-    if (subtype->Is<ast::type::Vector>()) {
-      subtype = subtype->As<ast::type::Vector>()->type()->UnwrapAll();
-    } else if (subtype->Is<ast::type::Matrix>()) {
-      subtype = subtype->As<ast::type::Matrix>()->type()->UnwrapAll();
-    } else if (subtype->Is<ast::type::Array>()) {
-      subtype = subtype->As<ast::type::Array>()->type()->UnwrapAll();
-    } else if (subtype->Is<ast::type::Struct>()) {
-      subtype = subtype->As<ast::type::Struct>()
-                    ->impl()
-                    ->members()[i]
-                    ->type()
-                    ->UnwrapAll();
+    if (auto* vec = subtype->As<ast::type::Vector>()) {
+      subtype = vec->type()->UnwrapAll();
+    } else if (auto* mat = subtype->As<ast::type::Matrix>()) {
+      subtype = mat->type()->UnwrapAll();
+    } else if (auto* arr = subtype->As<ast::type::Array>()) {
+      subtype = arr->type()->UnwrapAll();
+    } else if (auto* str = subtype->As<ast::type::Struct>()) {
+      subtype = str->impl()->members()[i]->type()->UnwrapAll();
     }
     if (subtype != sc->result_type()->UnwrapAll()) {
       return false;
@@ -1251,15 +1245,17 @@
 
   bool can_cast_or_copy = result_type->is_scalar();
 
-  if (result_type->Is<ast::type::Vector>() &&
-      result_type->As<ast::type::Vector>()->type()->is_scalar()) {
-    auto* value_type = values[0]->result_type()->UnwrapAll();
-    can_cast_or_copy =
-        (value_type->Is<ast::type::Vector>() &&
-         value_type->As<ast::type::Vector>()->type()->is_scalar() &&
-         result_type->As<ast::type::Vector>()->size() ==
-             value_type->As<ast::type::Vector>()->size());
+  if (auto* res_vec = result_type->As<ast::type::Vector>()) {
+    if (res_vec->type()->is_scalar()) {
+      auto* value_type = values[0]->result_type()->UnwrapAll();
+      if (auto* val_vec = value_type->As<ast::type::Vector>()) {
+        if (val_vec->type()->is_scalar()) {
+          can_cast_or_copy = res_vec->size() == val_vec->size();
+        }
+      }
+    }
   }
+
   if (can_cast_or_copy) {
     return GenerateCastOrCopyOrPassthrough(result_type, values[0]);
   }
@@ -1272,8 +1268,8 @@
   bool result_is_constant_composite = constructor_is_const;
   bool result_is_spec_composite = false;
 
-  if (result_type->Is<ast::type::Vector>()) {
-    result_type = result_type->As<ast::type::Vector>()->type();
+  if (auto* vec = result_type->As<ast::type::Vector>()) {
+    result_type = vec->type();
   }
 
   OperandList ops;
@@ -1321,8 +1317,7 @@
     //
     // For cases 1 and 2, if the type is different we also may need to insert
     // a type cast.
-    if (value_type->Is<ast::type::Vector>()) {
-      auto* vec = value_type->As<ast::type::Vector>();
+    if (auto* vec = value_type->As<ast::type::Vector>()) {
       auto* vec_type = vec->type();
 
       auto value_type_id = GenerateTypeIfNeeded(vec_type);
@@ -1488,8 +1483,8 @@
          Operand::Int(var->As<ast::DecoratedVariable>()->constant_id())});
   }
 
-  if (lit->Is<ast::BoolLiteral>()) {
-    if (lit->As<ast::BoolLiteral>()->IsTrue()) {
+  if (auto* l = lit->As<ast::BoolLiteral>()) {
+    if (l->IsTrue()) {
       push_type(is_spec_constant ? spv::Op::OpSpecConstantTrue
                                  : spv::Op::OpConstantTrue,
                 {Operand::Int(type_id), result});
@@ -1498,18 +1493,15 @@
                                  : spv::Op::OpConstantFalse,
                 {Operand::Int(type_id), result});
     }
-  } else if (lit->Is<ast::SintLiteral>()) {
+  } else if (auto* sl = lit->As<ast::SintLiteral>()) {
     push_type(is_spec_constant ? spv::Op::OpSpecConstant : spv::Op::OpConstant,
-              {Operand::Int(type_id), result,
-               Operand::Int(lit->As<ast::SintLiteral>()->value())});
-  } else if (lit->Is<ast::UintLiteral>()) {
+              {Operand::Int(type_id), result, Operand::Int(sl->value())});
+  } else if (auto* ul = lit->As<ast::UintLiteral>()) {
     push_type(is_spec_constant ? spv::Op::OpSpecConstant : spv::Op::OpConstant,
-              {Operand::Int(type_id), result,
-               Operand::Int(lit->As<ast::UintLiteral>()->value())});
-  } else if (lit->Is<ast::FloatLiteral>()) {
+              {Operand::Int(type_id), result, Operand::Int(ul->value())});
+  } else if (auto* fl = lit->As<ast::FloatLiteral>()) {
     push_type(is_spec_constant ? spv::Op::OpSpecConstant : spv::Op::OpConstant,
-              {Operand::Int(type_id), result,
-               Operand::Float(lit->As<ast::FloatLiteral>()->value())});
+              {Operand::Int(type_id), result, Operand::Float(fl->value())});
   } else if (lit->Is<ast::NullLiteral>()) {
     push_type(spv::Op::OpConstantNull, {Operand::Int(type_id), result});
   } else {
@@ -2413,8 +2405,8 @@
   }
 
   // The alias is a wrapper around the subtype, so emit the subtype
-  if (type->Is<ast::type::Alias>()) {
-    return GenerateTypeIfNeeded(type->As<ast::type::Alias>()->type());
+  if (auto* alias = type->As<ast::type::Alias>()) {
+    return GenerateTypeIfNeeded(alias->type());
   }
 
   auto val = type_name_to_id_.find(type->type_name());
@@ -2425,8 +2417,7 @@
   auto result = result_op();
   auto id = result.to_i();
 
-  if (type->Is<ast::type::AccessControl>()) {
-    auto* ac = type->As<ast::type::AccessControl>();
+  if (auto* ac = type->As<ast::type::AccessControl>()) {
     auto* subtype = ac->type()->UnwrapIfNeeded();
     if (!subtype->Is<ast::type::Struct>()) {
       error_ = "Access control attached to non-struct type.";
@@ -2436,8 +2427,8 @@
                             ac->access_control(), result)) {
       return 0;
     }
-  } else if (type->Is<ast::type::Array>()) {
-    if (!GenerateArray(type->As<ast::type::Array>(), result)) {
+  } else if (auto* arr = type->As<ast::type::Array>()) {
+    if (!GenerateArrayType(arr, result)) {
       return 0;
     }
   } else if (type->Is<ast::type::Bool>()) {
@@ -2446,29 +2437,28 @@
     push_type(spv::Op::OpTypeFloat, {result, Operand::Int(32)});
   } else if (type->Is<ast::type::I32>()) {
     push_type(spv::Op::OpTypeInt, {result, Operand::Int(32), Operand::Int(1)});
-  } else if (type->Is<ast::type::Matrix>()) {
-    if (!GenerateMatrixType(type->As<ast::type::Matrix>(), result)) {
+  } else if (auto* mat = type->As<ast::type::Matrix>()) {
+    if (!GenerateMatrixType(mat, result)) {
       return 0;
     }
-  } else if (type->Is<ast::type::Pointer>()) {
-    if (!GeneratePointerType(type->As<ast::type::Pointer>(), result)) {
+  } else if (auto* ptr = type->As<ast::type::Pointer>()) {
+    if (!GeneratePointerType(ptr, result)) {
       return 0;
     }
-  } else if (type->Is<ast::type::Struct>()) {
-    if (!GenerateStructType(type->As<ast::type::Struct>(),
-                            ast::AccessControl::kReadWrite, result)) {
+  } else if (auto* str = type->As<ast::type::Struct>()) {
+    if (!GenerateStructType(str, ast::AccessControl::kReadWrite, result)) {
       return 0;
     }
   } else if (type->Is<ast::type::U32>()) {
     push_type(spv::Op::OpTypeInt, {result, Operand::Int(32), Operand::Int(0)});
-  } else if (type->Is<ast::type::Vector>()) {
-    if (!GenerateVectorType(type->As<ast::type::Vector>(), result)) {
+  } else if (auto* vec = type->As<ast::type::Vector>()) {
+    if (!GenerateVectorType(vec, result)) {
       return 0;
     }
   } else if (type->Is<ast::type::Void>()) {
     push_type(spv::Op::OpTypeVoid, {result});
-  } else if (type->Is<ast::type::Texture>()) {
-    if (!GenerateTextureType(type->As<ast::type::Texture>(), result)) {
+  } else if (auto* tex = type->As<ast::type::Texture>()) {
+    if (!GenerateTextureType(tex, result)) {
       return 0;
     }
   } else if (type->Is<ast::type::Sampler>()) {
@@ -2546,20 +2536,16 @@
   if (texture->Is<ast::type::DepthTexture>()) {
     ast::type::F32 f32;
     type_id = GenerateTypeIfNeeded(&f32);
-  } else if (texture->Is<ast::type::SampledTexture>()) {
-    type_id =
-        GenerateTypeIfNeeded(texture->As<ast::type::SampledTexture>()->type());
-  } else if (texture->Is<ast::type::MultisampledTexture>()) {
-    type_id = GenerateTypeIfNeeded(
-        texture->As<ast::type::MultisampledTexture>()->type());
-  } else if (texture->Is<ast::type::StorageTexture>()) {
-    if (texture->As<ast::type::StorageTexture>()->access() ==
-        ast::AccessControl::kWriteOnly) {
+  } else if (auto* s = texture->As<ast::type::SampledTexture>()) {
+    type_id = GenerateTypeIfNeeded(s->type());
+  } else if (auto* ms = texture->As<ast::type::MultisampledTexture>()) {
+    type_id = GenerateTypeIfNeeded(ms->type());
+  } else if (auto* st = texture->As<ast::type::StorageTexture>()) {
+    if (st->access() == ast::AccessControl::kWriteOnly) {
       ast::type::Void void_type;
       type_id = GenerateTypeIfNeeded(&void_type);
     } else {
-      type_id = GenerateTypeIfNeeded(
-          texture->As<ast::type::StorageTexture>()->type());
+      type_id = GenerateTypeIfNeeded(st->type());
     }
   }
   if (type_id == 0u) {
@@ -2567,9 +2553,8 @@
   }
 
   uint32_t format_literal = SpvImageFormat_::SpvImageFormatUnknown;
-  if (texture->Is<ast::type::StorageTexture>()) {
-    format_literal = convert_image_format_to_spv(
-        texture->As<ast::type::StorageTexture>()->image_format());
+  if (auto* t = texture->As<ast::type::StorageTexture>()) {
+    format_literal = convert_image_format_to_spv(t->image_format());
   }
 
   push_type(spv::Op::OpTypeImage,
@@ -2581,7 +2566,7 @@
   return true;
 }
 
-bool Builder::GenerateArray(ast::type::Array* ary, const Operand& result) {
+bool Builder::GenerateArrayType(ast::type::Array* ary, const Operand& result) {
   auto elem_type = GenerateTypeIfNeeded(ary->type());
   if (elem_type == 0) {
     return false;
diff --git a/src/writer/spirv/builder.h b/src/writer/spirv/builder.h
index 0b32036..a5ffac3 100644
--- a/src/writer/spirv/builder.h
+++ b/src/writer/spirv/builder.h
@@ -431,7 +431,7 @@
   /// @param ary the array to generate
   /// @param result the result operand
   /// @returns true if the array was successfully generated
-  bool GenerateArray(ast::type::Array* ary, const Operand& result);
+  bool GenerateArrayType(ast::type::Array* ary, const Operand& result);
   /// Generates a matrix type declaration
   /// @param mat the matrix to generate
   /// @param result the result operand
diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc
index 85ac8ba..24d51a0 100644
--- a/src/writer/wgsl/generator_impl.cc
+++ b/src/writer/wgsl/generator_impl.cc
@@ -173,15 +173,14 @@
 
 bool GeneratorImpl::EmitConstructedType(const ast::type::Type* ty) {
   make_indent();
-  if (ty->Is<ast::type::Alias>()) {
-    auto* alias = ty->As<ast::type::Alias>();
+  if (auto* alias = ty->As<ast::type::Alias>()) {
     out_ << "type " << alias->name() << " = ";
     if (!EmitType(alias->type())) {
       return false;
     }
     out_ << ";" << std::endl;
-  } else if (ty->Is<ast::type::Struct>()) {
-    if (!EmitStructType(ty->As<ast::type::Struct>())) {
+  } else if (auto* str = ty->As<ast::type::Struct>()) {
+    if (!EmitStructType(str)) {
       return false;
     }
   } else {
@@ -321,14 +320,14 @@
 }
 
 bool GeneratorImpl::EmitLiteral(ast::Literal* lit) {
-  if (lit->Is<ast::BoolLiteral>()) {
-    out_ << (lit->As<ast::BoolLiteral>()->IsTrue() ? "true" : "false");
-  } else if (lit->Is<ast::FloatLiteral>()) {
-    out_ << FloatToString(lit->As<ast::FloatLiteral>()->value());
-  } else if (lit->Is<ast::SintLiteral>()) {
-    out_ << lit->As<ast::SintLiteral>()->value();
-  } else if (lit->Is<ast::UintLiteral>()) {
-    out_ << lit->As<ast::UintLiteral>()->value() << "u";
+  if (auto* bl = lit->As<ast::BoolLiteral>()) {
+    out_ << (bl->IsTrue() ? "true" : "false");
+  } else if (auto* fl = lit->As<ast::FloatLiteral>()) {
+    out_ << FloatToString(fl->value());
+  } else if (auto* sl = lit->As<ast::SintLiteral>()) {
+    out_ << sl->value();
+  } else if (auto* ul = lit->As<ast::UintLiteral>()) {
+    out_ << ul->value() << "u";
   } else {
     error_ = "unknown literal type";
     return false;
@@ -399,9 +398,7 @@
 }
 
 bool GeneratorImpl::EmitType(ast::type::Type* type) {
-  if (type->Is<ast::type::AccessControl>()) {
-    auto* ac = type->As<ast::type::AccessControl>();
-
+  if (auto* ac = type->As<ast::type::AccessControl>()) {
     out_ << "[[access(";
     if (ac->IsReadOnly()) {
       out_ << "read";
@@ -415,11 +412,9 @@
     if (!EmitType(ac->type())) {
       return false;
     }
-  } else if (type->Is<ast::type::Alias>()) {
-    out_ << type->As<ast::type::Alias>()->name();
-  } else if (type->Is<ast::type::Array>()) {
-    auto* ary = type->As<ast::type::Array>();
-
+  } else if (auto* alias = type->As<ast::type::Alias>()) {
+    out_ << alias->name();
+  } else if (auto* ary = type->As<ast::type::Array>()) {
     for (auto* deco : ary->decorations()) {
       if (auto* stride = deco->As<ast::StrideDecoration>()) {
         out_ << "[[stride(" << stride->stride() << ")]] ";
@@ -441,34 +436,29 @@
     out_ << "f32";
   } else if (type->Is<ast::type::I32>()) {
     out_ << "i32";
-  } else if (type->Is<ast::type::Matrix>()) {
-    auto* mat = type->As<ast::type::Matrix>();
+  } else if (auto* mat = type->As<ast::type::Matrix>()) {
     out_ << "mat" << mat->columns() << "x" << mat->rows() << "<";
     if (!EmitType(mat->type())) {
       return false;
     }
     out_ << ">";
-  } else if (type->Is<ast::type::Pointer>()) {
-    auto* ptr = type->As<ast::type::Pointer>();
+  } else if (auto* ptr = type->As<ast::type::Pointer>()) {
     out_ << "ptr<" << ptr->storage_class() << ", ";
     if (!EmitType(ptr->type())) {
       return false;
     }
     out_ << ">";
-  } else if (type->Is<ast::type::Sampler>()) {
-    auto* sampler = type->As<ast::type::Sampler>();
+  } else if (auto* sampler = type->As<ast::type::Sampler>()) {
     out_ << "sampler";
 
     if (sampler->IsComparison()) {
       out_ << "_comparison";
     }
-  } else if (type->Is<ast::type::Struct>()) {
+  } else if (auto* str = type->As<ast::type::Struct>()) {
     // The struct, as a type, is just the name. We should have already emitted
     // the declaration through a call to |EmitStructType| earlier.
-    out_ << type->As<ast::type::Struct>()->name();
-  } else if (type->Is<ast::type::Texture>()) {
-    auto* texture = type->As<ast::type::Texture>();
-
+    out_ << str->name();
+  } else if (auto* texture = type->As<ast::type::Texture>()) {
     out_ << "texture_";
     if (texture->Is<ast::type::DepthTexture>()) {
       out_ << "depth_";
@@ -476,10 +466,8 @@
       /* nothing to emit */
     } else if (texture->Is<ast::type::MultisampledTexture>()) {
       out_ << "multisampled_";
-    } else if (texture->Is<ast::type::StorageTexture>()) {
+    } else if (auto* storage = texture->As<ast::type::StorageTexture>()) {
       out_ << "storage_";
-
-      auto* storage = texture->As<ast::type::StorageTexture>();
       if (storage->access() == ast::AccessControl::kReadOnly) {
         out_ << "ro_";
       } else if (storage->access() == ast::AccessControl::kWriteOnly) {
@@ -520,25 +508,19 @@
         return false;
     }
 
-    if (texture->Is<ast::type::SampledTexture>()) {
-      auto* sampled = texture->As<ast::type::SampledTexture>();
-
+    if (auto* sampled = texture->As<ast::type::SampledTexture>()) {
       out_ << "<";
       if (!EmitType(sampled->type())) {
         return false;
       }
       out_ << ">";
-    } else if (texture->Is<ast::type::MultisampledTexture>()) {
-      auto* sampled = texture->As<ast::type::MultisampledTexture>();
-
+    } else if (auto* ms = texture->As<ast::type::MultisampledTexture>()) {
       out_ << "<";
-      if (!EmitType(sampled->type())) {
+      if (!EmitType(ms->type())) {
         return false;
       }
       out_ << ">";
-    } else if (texture->Is<ast::type::StorageTexture>()) {
-      auto* storage = texture->As<ast::type::StorageTexture>();
-
+    } else if (auto* storage = texture->As<ast::type::StorageTexture>()) {
       out_ << "<";
       if (!EmitImageFormat(storage->image_format())) {
         return false;
@@ -548,8 +530,7 @@
 
   } else if (type->Is<ast::type::U32>()) {
     out_ << "u32";
-  } else if (type->Is<ast::type::Vector>()) {
-    auto* vec = type->As<ast::type::Vector>();
+  } else if (auto* vec = type->As<ast::type::Vector>()) {
     out_ << "vec" << vec->size() << "<";
     if (!EmitType(vec->type())) {
       return false;
@@ -580,10 +561,9 @@
       make_indent();
 
       // TODO(dsinclair): Split this out when we have more then one
-      assert(deco->Is<ast::StructMemberOffsetDecoration>());
-      out_ << "[[offset("
-           << deco->As<ast::StructMemberOffsetDecoration>()->offset() << ")]]"
-           << std::endl;
+      auto* offset = deco->As<ast::StructMemberOffsetDecoration>();
+      assert(offset != nullptr);
+      out_ << "[[offset(" << offset->offset() << ")]]" << std::endl;
     }
     make_indent();
     out_ << mem->name() << " : ";
@@ -651,8 +631,8 @@
       out_ << "location(" << location->value() << ")";
     } else if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
       out_ << "builtin(" << builtin->value() << ")";
-    } else if (auto* cid = deco->As<ast::ConstantIdDecoration>()) {
-      out_ << "constant_id(" << cid->value() << ")";
+    } else if (auto* constant = deco->As<ast::ConstantIdDecoration>()) {
+      out_ << "constant_id(" << constant->value() << ")";
     } else {
       error_ = "unknown variable decoration";
       return false;