Prepare tests for switch to AST types

Register all aliases, and don't share type nodes

Bug: tint:724
Change-Id: I7ac20c8a75f232fa7fe1e8c1a5690f411888f6e4
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/49750
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
diff --git a/src/resolver/assignment_validation_test.cc b/src/resolver/assignment_validation_test.cc
index 2cbdcb9..be90145 100644
--- a/src/resolver/assignment_validation_test.cc
+++ b/src/resolver/assignment_validation_test.cc
@@ -167,6 +167,7 @@
   // var a :myint = 2;
   // a = 2
   auto myint = ty.alias("myint", ty.i32());
+  AST().AddConstructedType(myint);
   auto* var = Var("a", myint, ast::StorageClass::kNone, Expr(2));
 
   auto* lhs = Expr("a");
@@ -237,12 +238,14 @@
   // var b : [[access(read)]] texture_storage_1d<rgba8unorm>;
   // a = b;
 
-  auto tex_type = ty.storage_texture(ast::TextureDimension::k1d,
-                                     ast::ImageFormat::kRgba8Unorm);
-  auto tex_ac = ty.access(ast::AccessControl::kReadOnly, tex_type);
+  auto make_type = [&] {
+    auto tex_type = ty.storage_texture(ast::TextureDimension::k1d,
+                                       ast::ImageFormat::kRgba8Unorm);
+    return ty.access(ast::AccessControl::kReadOnly, tex_type);
+  };
 
-  auto* var_a = Var("a", tex_ac, ast::StorageClass::kFunction);
-  auto* var_b = Var("b", tex_ac, ast::StorageClass::kFunction);
+  auto* var_a = Var("a", make_type(), ast::StorageClass::kFunction);
+  auto* var_b = Var("b", make_type(), ast::StorageClass::kFunction);
 
   auto* lhs = Expr("a");
   auto* rhs = Expr("b");
diff --git a/src/resolver/builtins_validation_test.cc b/src/resolver/builtins_validation_test.cc
index 494a36d..9a1fdd4 100644
--- a/src/resolver/builtins_validation_test.cc
+++ b/src/resolver/builtins_validation_test.cc
@@ -27,21 +27,21 @@
 }
 
 TEST_F(ResolverBuiltinsValidationTest, Length_Float_Vec2) {
-  auto* builtin = Call("length", vec2<float>(1.0f, 1.0f));
+  auto* builtin = Call("length", vec2<f32>(1.0f, 1.0f));
   WrapInFunction(builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
 }
 
 TEST_F(ResolverBuiltinsValidationTest, Length_Float_Vec3) {
-  auto* builtin = Call("length", vec3<float>(1.0f, 1.0f, 1.0f));
+  auto* builtin = Call("length", vec3<f32>(1.0f, 1.0f, 1.0f));
   WrapInFunction(builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
 }
 
 TEST_F(ResolverBuiltinsValidationTest, Length_Float_Vec4) {
-  auto* builtin = Call("length", vec4<float>(1.0f, 1.0f, 1.0f, 1.0f));
+  auto* builtin = Call("length", vec4<f32>(1.0f, 1.0f, 1.0f, 1.0f));
   WrapInFunction(builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -56,41 +56,40 @@
 
 TEST_F(ResolverBuiltinsValidationTest, Distance_Float_Vec2) {
   auto* builtin =
-      Call("distance", vec2<float>(1.0f, 1.0f), vec2<float>(1.0f, 1.0f));
+      Call("distance", vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f));
   WrapInFunction(builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
 }
 
 TEST_F(ResolverBuiltinsValidationTest, Distance_Float_Vec3) {
-  auto* builtin = Call("distance", vec3<float>(1.0f, 1.0f, 1.0f),
-                       vec3<float>(1.0f, 1.0f, 1.0f));
+  auto* builtin = Call("distance", vec3<f32>(1.0f, 1.0f, 1.0f),
+                       vec3<f32>(1.0f, 1.0f, 1.0f));
   WrapInFunction(builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
 }
 
 TEST_F(ResolverBuiltinsValidationTest, Distance_Float_Vec4) {
-  auto* builtin = Call("distance", vec4<float>(1.0f, 1.0f, 1.0f, 1.0f),
-                       vec4<float>(1.0f, 1.0f, 1.0f, 1.0f));
+  auto* builtin = Call("distance", vec4<f32>(1.0f, 1.0f, 1.0f, 1.0f),
+                       vec4<f32>(1.0f, 1.0f, 1.0f, 1.0f));
   WrapInFunction(builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
 }
 
 TEST_F(ResolverBuiltinsValidationTest, Determinant_Mat2x2) {
-  auto* builtin = Call("determinant", mat2x2<float>(vec2<float>(1.0f, 1.0f),
-                                                    vec2<float>(1.0f, 1.0f)));
+  auto* builtin = Call(
+      "determinant", mat2x2<f32>(vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f)));
   WrapInFunction(builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
 }
 
 TEST_F(ResolverBuiltinsValidationTest, Determinant_Mat3x3) {
-  auto* builtin =
-      Call("determinant", mat3x3<float>(vec3<float>(1.0f, 1.0f, 1.0f),
-                                        vec3<float>(1.0f, 1.0f, 1.0f),
-                                        vec3<float>(1.0f, 1.0f, 1.0f)));
+  auto* builtin = Call("determinant", mat3x3<f32>(vec3<f32>(1.0f, 1.0f, 1.0f),
+                                                  vec3<f32>(1.0f, 1.0f, 1.0f),
+                                                  vec3<f32>(1.0f, 1.0f, 1.0f)));
   WrapInFunction(builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -98,10 +97,10 @@
 
 TEST_F(ResolverBuiltinsValidationTest, Determinant_Mat4x4) {
   auto* builtin =
-      Call("determinant", mat4x4<float>(vec4<float>(1.0f, 1.0f, 1.0f, 1.0f),
-                                        vec4<float>(1.0f, 1.0f, 1.0f, 1.0f),
-                                        vec4<float>(1.0f, 1.0f, 1.0f, 1.0f),
-                                        vec4<float>(1.0f, 1.0f, 1.0f, 1.0f)));
+      Call("determinant", mat4x4<f32>(vec4<f32>(1.0f, 1.0f, 1.0f, 1.0f),
+                                      vec4<f32>(1.0f, 1.0f, 1.0f, 1.0f),
+                                      vec4<f32>(1.0f, 1.0f, 1.0f, 1.0f),
+                                      vec4<f32>(1.0f, 1.0f, 1.0f, 1.0f)));
   WrapInFunction(builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -119,11 +118,9 @@
 
 TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec2) {
   auto* a = Var("a", ty.vec2<int>(), ast::StorageClass::kFunction);
-  auto* b = Const("b",
-                  create<sem::Pointer>(create<sem::Vector>(ty.i32(), 2),
-                                       ast::StorageClass::kFunction),
+  auto* b = Const("b", ty.pointer(ty.vec2<i32>(), ast::StorageClass::kFunction),
                   Expr("a"), {});
-  auto* builtin = Call("frexp", vec2<float>(1.0f, 1.0f), Expr("b"));
+  auto* builtin = Call("frexp", vec2<f32>(1.0f, 1.0f), Expr("b"));
   WrapInFunction(Decl(a), Decl(b), builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -133,11 +130,9 @@
 
 TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec3) {
   auto* a = Var("a", ty.vec3<int>(), ast::StorageClass::kFunction);
-  auto* b = Const("b",
-                  create<sem::Pointer>(create<sem::Vector>(ty.i32(), 3),
-                                       ast::StorageClass::kFunction),
+  auto* b = Const("b", ty.pointer(ty.vec3<i32>(), ast::StorageClass::kFunction),
                   Expr("a"), {});
-  auto* builtin = Call("frexp", vec3<float>(1.0f, 1.0f, 1.0f), Expr("b"));
+  auto* builtin = Call("frexp", vec3<f32>(1.0f, 1.0f, 1.0f), Expr("b"));
   WrapInFunction(Decl(a), Decl(b), builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -147,11 +142,9 @@
 
 TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec4) {
   auto* a = Var("a", ty.vec4<int>(), ast::StorageClass::kFunction);
-  auto* b = Const("b",
-                  create<sem::Pointer>(create<sem::Vector>(ty.i32(), 4),
-                                       ast::StorageClass::kFunction),
+  auto* b = Const("b", ty.pointer(ty.vec4<i32>(), ast::StorageClass::kFunction),
                   Expr("a"), {});
-  auto* builtin = Call("frexp", vec4<float>(1.0f, 1.0f, 1.0f, 1.0f), Expr("b"));
+  auto* builtin = Call("frexp", vec4<f32>(1.0f, 1.0f, 1.0f, 1.0f), Expr("b"));
   WrapInFunction(Decl(a), Decl(b), builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -161,8 +154,8 @@
 
 TEST_F(ResolverBuiltinsValidationTest, Modf_Scalar) {
   auto* a = Var("a", ty.f32(), ast::StorageClass::kFunction);
-  auto* b = Const("b", ty.pointer<float>(ast::StorageClass::kFunction),
-                  Expr("a"), {});
+  auto* b =
+      Const("b", ty.pointer<f32>(ast::StorageClass::kFunction), Expr("a"), {});
   auto* builtin = Call("modf", 1.0f, Expr("b"));
   WrapInFunction(Decl(a), Decl(b), builtin);
 
@@ -172,12 +165,10 @@
 }
 
 TEST_F(ResolverBuiltinsValidationTest, Modf_Vec2) {
-  auto* a = Var("a", ty.vec2<float>(), ast::StorageClass::kFunction);
-  auto* b = Const("b",
-                  create<sem::Pointer>(create<sem::Vector>(ty.f32(), 2),
-                                       ast::StorageClass::kFunction),
+  auto* a = Var("a", ty.vec2<f32>(), ast::StorageClass::kFunction);
+  auto* b = Const("b", ty.pointer(ty.vec2<f32>(), ast::StorageClass::kFunction),
                   Expr("a"), {});
-  auto* builtin = Call("modf", vec2<float>(1.0f, 1.0f), Expr("b"));
+  auto* builtin = Call("modf", vec2<f32>(1.0f, 1.0f), Expr("b"));
   WrapInFunction(Decl(a), Decl(b), builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -186,12 +177,10 @@
 }
 
 TEST_F(ResolverBuiltinsValidationTest, Modf_Vec3) {
-  auto* a = Var("a", ty.vec3<float>(), ast::StorageClass::kFunction);
-  auto* b = Const("b",
-                  create<sem::Pointer>(create<sem::Vector>(ty.f32(), 3),
-                                       ast::StorageClass::kFunction),
+  auto* a = Var("a", ty.vec3<f32>(), ast::StorageClass::kFunction);
+  auto* b = Const("b", ty.pointer(ty.vec3<f32>(), ast::StorageClass::kFunction),
                   Expr("a"), {});
-  auto* builtin = Call("modf", vec3<float>(1.0f, 1.0f, 1.0f), Expr("b"));
+  auto* builtin = Call("modf", vec3<f32>(1.0f, 1.0f, 1.0f), Expr("b"));
   WrapInFunction(Decl(a), Decl(b), builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -200,12 +189,10 @@
 }
 
 TEST_F(ResolverBuiltinsValidationTest, Modf_Vec4) {
-  auto* a = Var("a", ty.vec4<float>(), ast::StorageClass::kFunction);
-  auto* b = Const("b",
-                  create<sem::Pointer>(create<sem::Vector>(ty.f32(), 4),
-                                       ast::StorageClass::kFunction),
+  auto* a = Var("a", ty.vec4<f32>(), ast::StorageClass::kFunction);
+  auto* b = Const("b", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction),
                   Expr("a"), {});
-  auto* builtin = Call("modf", vec4<float>(1.0f, 1.0f, 1.0f, 1.0f), Expr("b"));
+  auto* builtin = Call("modf", vec4<f32>(1.0f, 1.0f, 1.0f, 1.0f), Expr("b"));
   WrapInFunction(Decl(a), Decl(b), builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -214,15 +201,15 @@
 }
 
 TEST_F(ResolverBuiltinsValidationTest, Cross_Float_Vec3) {
-  auto* builtin = Call("cross", vec3<float>(1.0f, 1.0f, 1.0f),
-                       vec3<float>(1.0f, 1.0f, 1.0f));
+  auto* builtin =
+      Call("cross", vec3<f32>(1.0f, 1.0f, 1.0f), vec3<f32>(1.0f, 1.0f, 1.0f));
   WrapInFunction(builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
 }
 
 TEST_F(ResolverBuiltinsValidationTest, Dot_Float_Vec2) {
-  auto* builtin = Call("dot", vec2<float>(1.0f, 1.0f), vec2<float>(1.0f, 1.0f));
+  auto* builtin = Call("dot", vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f));
   WrapInFunction(builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -230,15 +217,15 @@
 
 TEST_F(ResolverBuiltinsValidationTest, Dot_Float_Vec3) {
   auto* builtin =
-      Call("dot", vec3<float>(1.0f, 1.0f, 1.0f), vec3<float>(1.0f, 1.0f, 1.0f));
+      Call("dot", vec3<f32>(1.0f, 1.0f, 1.0f), vec3<f32>(1.0f, 1.0f, 1.0f));
   WrapInFunction(builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
 }
 
 TEST_F(ResolverBuiltinsValidationTest, Dot_Float_Vec4) {
-  auto* builtin = Call("dot", vec4<float>(1.0f, 1.0f, 1.0f, 1.0f),
-                       vec4<float>(1.0f, 1.0f, 1.0f, 1.0f));
+  auto* builtin = Call("dot", vec4<f32>(1.0f, 1.0f, 1.0f, 1.0f),
+                       vec4<f32>(1.0f, 1.0f, 1.0f, 1.0f));
   WrapInFunction(builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -266,8 +253,8 @@
 }
 
 TEST_F(ResolverBuiltinsValidationTest, Select_Float_Vec2) {
-  auto* builtin = Call("select", vec2<float>(1.0f, 1.0f),
-                       vec2<float>(1.0f, 1.0f), vec2<bool>(true, true));
+  auto* builtin = Call("select", vec2<f32>(1.0f, 1.0f), vec2<f32>(1.0f, 1.0f),
+                       vec2<bool>(true, true));
   WrapInFunction(builtin);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -318,7 +305,7 @@
 
   ast::ExpressionList params;
   for (uint32_t i = 0; i < num_params; ++i) {
-    params.push_back(vec2<float>(1.0f, 1.0f));
+    params.push_back(vec2<f32>(1.0f, 1.0f));
   }
   auto* builtin = Call(name, params);
   WrapInFunction(builtin);
@@ -333,7 +320,7 @@
 
   ast::ExpressionList params;
   for (uint32_t i = 0; i < num_params; ++i) {
-    params.push_back(vec3<float>(1.0f, 1.0f, 1.0f));
+    params.push_back(vec3<f32>(1.0f, 1.0f, 1.0f));
   }
   auto* builtin = Call(name, params);
   WrapInFunction(builtin);
@@ -348,7 +335,7 @@
 
   ast::ExpressionList params;
   for (uint32_t i = 0; i < num_params; ++i) {
-    params.push_back(vec4<float>(1.0f, 1.0f, 1.0f, 1.0f));
+    params.push_back(vec4<f32>(1.0f, 1.0f, 1.0f, 1.0f));
   }
   auto* builtin = Call(name, params);
   WrapInFunction(builtin);
@@ -588,7 +575,7 @@
 
 TEST_P(DataPacking4x8, Float_Vec4) {
   auto name = GetParam();
-  auto* builtin = Call(name, vec4<float>(1.0f, 1.0f, 1.0f, 1.0f));
+  auto* builtin = Call(name, vec4<f32>(1.0f, 1.0f, 1.0f, 1.0f));
   WrapInFunction(builtin);
   EXPECT_TRUE(r()->Resolve()) << r()->error();
 }
@@ -601,7 +588,7 @@
 
 TEST_P(DataPacking2x16, Float_Vec2) {
   auto name = GetParam();
-  auto* builtin = Call(name, vec2<float>(1.0f, 1.0f));
+  auto* builtin = Call(name, vec2<f32>(1.0f, 1.0f));
   WrapInFunction(builtin);
   EXPECT_TRUE(r()->Resolve()) << r()->error();
 }
diff --git a/src/resolver/function_validation_test.cc b/src/resolver/function_validation_test.cc
index 9ffb314..542ed2d 100644
--- a/src/resolver/function_validation_test.cc
+++ b/src/resolver/function_validation_test.cc
@@ -158,6 +158,7 @@
   // type myf32 = f32;
   // fn func -> myf32 { return 2.0; }
   auto myf32 = ty.alias("myf32", ty.f32());
+  AST().AddConstructedType(myf32);
   Func("func", ast::VariableList{}, myf32,
        ast::StatementList{
            Return(Source{Source::Location{12, 34}}, Expr(2.f)),
@@ -172,6 +173,7 @@
   // type myf32 = f32;
   // fn func -> myf32 { return 2; }
   auto myf32 = ty.alias("myf32", ty.f32());
+  AST().AddConstructedType(myf32);
   Func("func", ast::VariableList{}, myf32,
        ast::StatementList{
            Return(Source{Source::Location{12, 34}}, Expr(2u)),
diff --git a/src/resolver/host_shareable_validation_test.cc b/src/resolver/host_shareable_validation_test.cc
index 3990c5e..ec04c2e 100644
--- a/src/resolver/host_shareable_validation_test.cc
+++ b/src/resolver/host_shareable_validation_test.cc
@@ -58,10 +58,12 @@
 
 TEST_F(ResolverHostShareableValidationTest, Aliases) {
   auto a1 = ty.alias("a1", ty.bool_());
+  AST().AddConstructedType(a1);
   auto s = Structure("S", {Member(Source{{12, 34}}, "x", a1)},
                      {create<ast::StructBlockDecoration>()});
   auto ac = ty.access(ast::AccessControl::kReadOnly, s);
   auto a2 = ty.alias("a2", ac);
+  AST().AddConstructedType(a2);
   Global(Source{{56, 78}}, "g", a2, ast::StorageClass::kStorage);
 
   ASSERT_FALSE(r()->Resolve());
@@ -102,17 +104,20 @@
                           Member(Source{{2, 1}}, "y1", ty.vec3<f32>()),
                           Member(Source{{3, 1}}, "z1", ty.array<i32, 4>()),
                       });
+  auto a1 = ty.alias("a1", i1);
+  AST().AddConstructedType(a1);
   auto i2 = Structure("I2", {
                                 Member(Source{{4, 1}}, "x2", ty.mat2x2<f32>()),
                                 Member(Source{{5, 1}}, "y2", i1),
                                 Member(Source{{6, 1}}, "z2", ty.mat3x2<i32>()),
                             });
-  auto i3 =
-      Structure("I3", {
-                          Member(Source{{4, 1}}, "x3", ty.alias("a1", i1)),
-                          Member(Source{{5, 1}}, "y3", i2),
-                          Member(Source{{6, 1}}, "z3", ty.alias("a2", i2)),
-                      });
+  auto a2 = ty.alias("a2", i2);
+  AST().AddConstructedType(a2);
+  auto i3 = Structure("I3", {
+                                Member(Source{{4, 1}}, "x3", a1),
+                                Member(Source{{5, 1}}, "y3", i2),
+                                Member(Source{{6, 1}}, "z3", a2),
+                            });
 
   auto s = Structure("S", {Member(Source{{7, 8}}, "m", i3)},
                      {create<ast::StructBlockDecoration>()});
diff --git a/src/resolver/intrinsic_test.cc b/src/resolver/intrinsic_test.cc
index ed85faa..7233f18 100644
--- a/src/resolver/intrinsic_test.cc
+++ b/src/resolver/intrinsic_test.cc
@@ -1947,9 +1947,19 @@
       case ast::intrinsic::test::TextureKind::kRegular:
       case ast::intrinsic::test::TextureKind::kMultisampled:
       case ast::intrinsic::test::TextureKind::kStorage: {
-        auto datatype = param.resultVectorComponentType(this);
-        ASSERT_TRUE(TypeOf(call)->Is<sem::Vector>());
-        EXPECT_EQ(TypeOf(call)->As<sem::Vector>()->type(), datatype);
+        auto* vec = TypeOf(call)->As<sem::Vector>();
+        ASSERT_NE(vec, nullptr);
+        switch (param.texture_data_type) {
+          case ast::intrinsic::test::TextureDataType::kF32:
+            EXPECT_TRUE(vec->type()->Is<sem::F32>());
+            break;
+          case ast::intrinsic::test::TextureDataType::kU32:
+            EXPECT_TRUE(vec->type()->Is<sem::U32>());
+            break;
+          case ast::intrinsic::test::TextureDataType::kI32:
+            EXPECT_TRUE(vec->type()->Is<sem::I32>());
+            break;
+        }
         break;
       }
       case ast::intrinsic::test::TextureKind::kDepth: {
diff --git a/src/resolver/is_storeable_test.cc b/src/resolver/is_storeable_test.cc
index 63afa1f..eb7b391 100644
--- a/src/resolver/is_storeable_test.cc
+++ b/src/resolver/is_storeable_test.cc
@@ -39,24 +39,24 @@
   EXPECT_TRUE(r()->IsStorable(ty.vec2<i32>()));
   EXPECT_TRUE(r()->IsStorable(ty.vec3<i32>()));
   EXPECT_TRUE(r()->IsStorable(ty.vec4<i32>()));
-  EXPECT_TRUE(r()->IsStorable(ty.vec2<unsigned>()));
-  EXPECT_TRUE(r()->IsStorable(ty.vec3<unsigned>()));
-  EXPECT_TRUE(r()->IsStorable(ty.vec4<unsigned>()));
-  EXPECT_TRUE(r()->IsStorable(ty.vec2<float>()));
-  EXPECT_TRUE(r()->IsStorable(ty.vec3<float>()));
-  EXPECT_TRUE(r()->IsStorable(ty.vec4<float>()));
+  EXPECT_TRUE(r()->IsStorable(ty.vec2<u32>()));
+  EXPECT_TRUE(r()->IsStorable(ty.vec3<u32>()));
+  EXPECT_TRUE(r()->IsStorable(ty.vec4<u32>()));
+  EXPECT_TRUE(r()->IsStorable(ty.vec2<f32>()));
+  EXPECT_TRUE(r()->IsStorable(ty.vec3<f32>()));
+  EXPECT_TRUE(r()->IsStorable(ty.vec4<f32>()));
 }
 
 TEST_F(ResolverIsStorableTest, Matrix) {
-  EXPECT_TRUE(r()->IsStorable(ty.mat2x2<float>()));
-  EXPECT_TRUE(r()->IsStorable(ty.mat2x3<float>()));
-  EXPECT_TRUE(r()->IsStorable(ty.mat2x4<float>()));
-  EXPECT_TRUE(r()->IsStorable(ty.mat3x2<float>()));
-  EXPECT_TRUE(r()->IsStorable(ty.mat3x3<float>()));
-  EXPECT_TRUE(r()->IsStorable(ty.mat3x4<float>()));
-  EXPECT_TRUE(r()->IsStorable(ty.mat4x2<float>()));
-  EXPECT_TRUE(r()->IsStorable(ty.mat4x3<float>()));
-  EXPECT_TRUE(r()->IsStorable(ty.mat4x4<float>()));
+  EXPECT_TRUE(r()->IsStorable(ty.mat2x2<f32>()));
+  EXPECT_TRUE(r()->IsStorable(ty.mat2x3<f32>()));
+  EXPECT_TRUE(r()->IsStorable(ty.mat2x4<f32>()));
+  EXPECT_TRUE(r()->IsStorable(ty.mat3x2<f32>()));
+  EXPECT_TRUE(r()->IsStorable(ty.mat3x3<f32>()));
+  EXPECT_TRUE(r()->IsStorable(ty.mat3x4<f32>()));
+  EXPECT_TRUE(r()->IsStorable(ty.mat4x2<f32>()));
+  EXPECT_TRUE(r()->IsStorable(ty.mat4x3<f32>()));
+  EXPECT_TRUE(r()->IsStorable(ty.mat4x4<f32>()));
 }
 
 TEST_F(ResolverIsStorableTest, Pointer) {
diff --git a/src/resolver/resolver_test.cc b/src/resolver/resolver_test.cc
index a3ddc26..3c67637 100644
--- a/src/resolver/resolver_test.cc
+++ b/src/resolver/resolver_test.cc
@@ -261,6 +261,7 @@
 
 TEST_F(ResolverTest, Stmt_VariableDecl_Alias) {
   auto my_int = ty.alias("MyInt", ty.i32());
+  AST().AddConstructedType(my_int);
   auto* var = Var("my_var", my_int, ast::StorageClass::kNone, Expr(2));
   auto* init = var->constructor();
 
@@ -408,6 +409,7 @@
 
 TEST_F(ResolverTest, Expr_ArrayAccessor_Alias_Array) {
   auto aary = ty.alias("myarrty", ty.array<f32, 3>());
+  AST().AddConstructedType(aary);
 
   Global("my_var", aary, ast::StorageClass::kFunction);
 
@@ -904,9 +906,10 @@
 }
 
 TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) {
-  auto st = Structure("alias", {Member("first_member", ty.i32()),
-                                Member("second_member", ty.f32())});
+  auto st = Structure("S", {Member("first_member", ty.i32()),
+                            Member("second_member", ty.f32())});
   auto alias = ty.alias("alias", st);
+  AST().AddConstructedType(alias);
   Global("my_struct", alias, ast::StorageClass::kInput);
 
   auto* mem = MemberAccessor("my_struct", "second_member");
@@ -985,10 +988,7 @@
   //
 
   auto stB = Structure("B", {Member("foo", ty.vec4<f32>())});
-
-  sem::Vector vecB(stB, 3);
-
-  auto stA = Structure("A", {Member("mem", &vecB)});
+  auto stA = Structure("A", {Member("mem", ty.vec(stB, 3))});
   Global("c", stA, ast::StorageClass::kInput);
 
   auto* mem = MemberAccessor(
diff --git a/src/resolver/storage_class_validation_test.cc b/src/resolver/storage_class_validation_test.cc
index a1c79c4..875cffa 100644
--- a/src/resolver/storage_class_validation_test.cc
+++ b/src/resolver/storage_class_validation_test.cc
@@ -76,6 +76,7 @@
   // type a = bool;
   // var<storage> g : [[access(read)]] a;
   auto a = ty.alias("a", ty.bool_());
+  AST().AddConstructedType(a);
   Global(Source{{56, 78}}, "g", a, ast::StorageClass::kStorage);
 
   ASSERT_FALSE(r()->Resolve());
@@ -131,8 +132,10 @@
   auto s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())},
                      {create<ast::StructBlockDecoration>()});
   auto a1 = ty.alias("a1", s);
+  AST().AddConstructedType(a1);
   auto ac = ty.access(ast::AccessControl::kReadOnly, a1);
   auto a2 = ty.alias("a2", ac);
+  AST().AddConstructedType(a2);
   Global(Source{{56, 78}}, "g", a2, ast::StorageClass::kStorage);
 
   ASSERT_TRUE(r()->Resolve());
@@ -181,6 +184,7 @@
   // type a = bool;
   // var<uniform> g : [[access(read)]] a;
   auto a = ty.alias("a", ty.bool_());
+  AST().AddConstructedType(a);
   Global(Source{{56, 78}}, "g", a, ast::StorageClass::kUniform);
 
   ASSERT_FALSE(r()->Resolve());
@@ -221,6 +225,7 @@
   auto s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())},
                      {create<ast::StructBlockDecoration>()});
   auto a1 = ty.alias("a1", s);
+  AST().AddConstructedType(a1);
   Global(Source{{56, 78}}, "g", a1, ast::StorageClass::kUniform);
 
   ASSERT_TRUE(r()->Resolve());
diff --git a/src/resolver/struct_layout_test.cc b/src/resolver/struct_layout_test.cc
index 67e1335..1a17706 100644
--- a/src/resolver/struct_layout_test.cc
+++ b/src/resolver/struct_layout_test.cc
@@ -52,9 +52,14 @@
 }
 
 TEST_F(ResolverStructLayoutTest, Alias) {
+  auto alias_a = ty.alias("a", ty.f32());
+  AST().AddConstructedType(alias_a);
+  auto alias_b = ty.alias("b", ty.f32());
+  AST().AddConstructedType(alias_b);
+
   auto s = Structure("S", {
-                              Member("a", ty.alias("a", ty.f32())),
-                              Member("b", ty.alias("b", ty.f32())),
+                              Member("a", alias_a),
+                              Member("b", alias_b),
                           });
 
   ASSERT_TRUE(r()->Resolve()) << r()->error();
diff --git a/src/resolver/struct_pipeline_stage_use_test.cc b/src/resolver/struct_pipeline_stage_use_test.cc
index 52e954c..35e7a53 100644
--- a/src/resolver/struct_pipeline_stage_use_test.cc
+++ b/src/resolver/struct_pipeline_stage_use_test.cc
@@ -159,6 +159,7 @@
 TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderParamViaAlias) {
   auto s = Structure("S", {Member("a", ty.f32(), {Location(0)})});
   auto s_alias = ty.alias("S_alias", s);
+  AST().AddConstructedType(s_alias);
 
   Func("main", {Param("param", s_alias)}, ty.void_(), {},
        {Stage(ast::PipelineStage::kFragment)});
@@ -174,6 +175,7 @@
 TEST_F(ResolverPipelineStageUseTest, StructUsedAsShaderReturnTypeViaAlias) {
   auto s = Structure("S", {Member("a", ty.f32(), {Location(0)})});
   auto s_alias = ty.alias("S_alias", s);
+  AST().AddConstructedType(s_alias);
 
   Func("main", {}, s_alias, {Return(Construct(s_alias, Expr(0.f)))},
        {Stage(ast::PipelineStage::kFragment)});
diff --git a/src/resolver/struct_storage_class_use_test.cc b/src/resolver/struct_storage_class_use_test.cc
index b17f512..9f6d2e4 100644
--- a/src/resolver/struct_storage_class_use_test.cc
+++ b/src/resolver/struct_storage_class_use_test.cc
@@ -79,6 +79,7 @@
 TEST_F(ResolverStorageClassUseTest, StructReachableViaGlobalAlias) {
   auto s = Structure("S", {Member("a", ty.f32())});
   auto a = ty.alias("A", s);
+  AST().AddConstructedType(a);
   Global("g", a, ast::StorageClass::kPrivate);
 
   ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -131,6 +132,7 @@
 TEST_F(ResolverStorageClassUseTest, StructReachableViaLocalAlias) {
   auto s = Structure("S", {Member("a", ty.f32())});
   auto a = ty.alias("A", s);
+  AST().AddConstructedType(a);
   WrapInFunction(Var("g", a, ast::StorageClass::kFunction));
 
   ASSERT_TRUE(r()->Resolve()) << r()->error();
diff --git a/src/resolver/type_validation_test.cc b/src/resolver/type_validation_test.cc
index eacae8e..d4abb28 100644
--- a/src/resolver/type_validation_test.cc
+++ b/src/resolver/type_validation_test.cc
@@ -402,6 +402,7 @@
   //}
 
   auto alias = ty.alias("RTArr", ty.array<u32>());
+  AST().AddConstructedType(alias);
 
   Structure("s",
             {
@@ -428,6 +429,7 @@
   //}
 
   auto alias = ty.alias("RTArr", ty.array<u32>());
+  AST().AddConstructedType(alias);
 
   Structure("s",
             {
diff --git a/src/resolver/validation_test.cc b/src/resolver/validation_test.cc
index 8adf825..c76e396 100644
--- a/src/resolver/validation_test.cc
+++ b/src/resolver/validation_test.cc
@@ -165,6 +165,7 @@
 TEST_F(ResolverValidationTest,
        Stmt_VariableDecl_MismatchedTypeScalarConstructor_Alias) {
   auto my_int = ty.alias("MyInt", ty.i32());
+  AST().AddConstructedType(my_int);
   u32 unsigned_value = 2u;  // Type does not match variable type
   auto* var =
       Var("my_var", my_int, ast::StorageClass::kNone, Expr(unsigned_value));
@@ -1685,6 +1686,7 @@
 
 TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Error) {
   auto alias = ty.alias("UnsignedInt", ty.u32());
+  AST().AddConstructedType(alias);
   Global("uint_var", alias, ast::StorageClass::kInput);
 
   auto* tc = vec2<f32>(Expr(Source{{12, 34}}, "uint_var"));
@@ -1699,6 +1701,8 @@
 TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Success) {
   auto f32_alias = ty.alias("Float32", ty.f32());
   auto vec2_alias = ty.alias("VectorFloat2", ty.vec2<f32>());
+  AST().AddConstructedType(f32_alias);
+  AST().AddConstructedType(vec2_alias);
   Global("my_f32", f32_alias, ast::StorageClass::kInput);
   Global("my_vec2", vec2_alias, ast::StorageClass::kInput);
 
@@ -1709,9 +1713,10 @@
 
 TEST_F(ResolverValidationTest, Expr_Constructor_Vector_ElementTypeAlias_Error) {
   auto f32_alias = ty.alias("Float32", ty.f32());
-  auto* vec_type = create<sem::Vector>(f32_alias, 2);
+  AST().AddConstructedType(f32_alias);
 
   // vec2<Float32>(1.0f, 1u)
+  auto vec_type = ty.vec(f32_alias, 2);
   auto* tc = create<ast::TypeConstructorExpression>(
       Source{{12, 34}}, vec_type,
       ExprList(1.0f, create<ast::ScalarConstructorExpression>(Source{{12, 40}},
@@ -1727,9 +1732,10 @@
 TEST_F(ResolverValidationTest,
        Expr_Constructor_Vector_ElementTypeAlias_Success) {
   auto f32_alias = ty.alias("Float32", ty.f32());
-  auto* vec_type = create<sem::Vector>(f32_alias, 2);
+  AST().AddConstructedType(f32_alias);
 
   // vec2<Float32>(1.0f, 1.0f)
+  auto vec_type = ty.vec(f32_alias, 2);
   auto* tc = create<ast::TypeConstructorExpression>(Source{{12, 34}}, vec_type,
                                                     ExprList(1.0f, 1.0f));
   WrapInFunction(tc);
@@ -1740,9 +1746,10 @@
 TEST_F(ResolverValidationTest,
        Expr_Constructor_Vector_ArgumentElementTypeAlias_Error) {
   auto f32_alias = ty.alias("Float32", ty.f32());
-  auto* vec_type = create<sem::Vector>(f32_alias, 2);
+  AST().AddConstructedType(f32_alias);
 
   // vec3<u32>(vec<Float32>(), 1.0f)
+  auto vec_type = ty.vec(f32_alias, 2);
   auto* tc = vec3<u32>(create<ast::TypeConstructorExpression>(
                            Source{{12, 34}}, vec_type, ExprList()),
                        1.0f);
@@ -1757,9 +1764,10 @@
 TEST_F(ResolverValidationTest,
        Expr_Constructor_Vector_ArgumentElementTypeAlias_Success) {
   auto f32_alias = ty.alias("Float32", ty.f32());
-  auto* vec_type = create<sem::Vector>(f32_alias, 2);
+  AST().AddConstructedType(f32_alias);
 
   // vec3<f32>(vec<Float32>(), 1.0f)
+  auto vec_type = ty.vec(f32_alias, 2);
   auto* tc = vec3<f32>(create<ast::TypeConstructorExpression>(
                            Source{{12, 34}}, vec_type, ExprList()),
                        1.0f);
@@ -1789,15 +1797,15 @@
   // matNxM<f32>(vecM<f32>(), ...); with N - 1 arguments
 
   const auto param = GetParam();
-  auto matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto vec_type = ty.vec<f32>(param.rows);
 
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns - 1; i++) {
+    auto vec_type = ty.vec<f32>(param.rows);
     args.push_back(create<ast::TypeConstructorExpression>(
         Source{{12, i}}, vec_type, ExprList()));
   }
 
+  auto matrix_type = ty.mat<f32>(param.columns, param.rows);
   auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
                                                     std::move(args));
   WrapInFunction(tc);
@@ -1813,15 +1821,15 @@
   // matNxM<f32>(vecM<f32>(), ...); with N + 1 arguments
 
   const auto param = GetParam();
-  auto matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto vec_type = ty.vec<f32>(param.rows);
 
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns + 1; i++) {
+    auto vec_type = ty.vec<f32>(param.rows);
     args.push_back(create<ast::TypeConstructorExpression>(
         Source{{12, i}}, vec_type, ExprList()));
   }
 
+  auto matrix_type = ty.mat<f32>(param.columns, param.rows);
   auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
                                                     std::move(args));
   WrapInFunction(tc);
@@ -1837,7 +1845,6 @@
   // matNxM<f32>(1.0, 1.0, ...); N arguments
 
   const auto param = GetParam();
-  auto matrix_type = ty.mat<f32>(param.columns, param.rows);
 
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns; i++) {
@@ -1845,6 +1852,7 @@
                                                             Literal(1.0f)));
   }
 
+  auto matrix_type = ty.mat<f32>(param.columns, param.rows);
   auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
                                                     std::move(args));
   WrapInFunction(tc);
@@ -1866,19 +1874,18 @@
     return;
   }
 
-  auto matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto valid_vec_type = ty.vec<f32>(param.rows);
-  auto invalid_vec_type = ty.vec<f32>(param.rows - 1);
-
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns - 1; i++) {
+    auto valid_vec_type = ty.vec<f32>(param.rows);
     args.push_back(create<ast::TypeConstructorExpression>(
         Source{{12, i}}, valid_vec_type, ExprList()));
   }
   const size_t kInvalidLoc = 2 * (param.columns - 1);
+  auto invalid_vec_type = ty.vec<f32>(param.rows - 1);
   args.push_back(create<ast::TypeConstructorExpression>(
       Source{{12, kInvalidLoc}}, invalid_vec_type, ExprList()));
 
+  auto matrix_type = ty.mat<f32>(param.columns, param.rows);
   auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
                                                     std::move(args));
   WrapInFunction(tc);
@@ -1902,19 +1909,18 @@
     return;
   }
 
-  auto matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto valid_vec_type = ty.vec<f32>(param.rows);
-  auto invalid_vec_type = ty.vec<f32>(param.rows + 1);
-
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns - 1; i++) {
+    auto valid_vec_type = ty.vec<f32>(param.rows);
     args.push_back(create<ast::TypeConstructorExpression>(
         Source{{12, i}}, valid_vec_type, ExprList()));
   }
   const size_t kInvalidLoc = 2 * (param.columns - 1);
+  auto invalid_vec_type = ty.vec<f32>(param.rows + 1);
   args.push_back(create<ast::TypeConstructorExpression>(
       Source{{12, kInvalidLoc}}, invalid_vec_type, ExprList()));
 
+  auto matrix_type = ty.mat<f32>(param.columns, param.rows);
   auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
                                                     std::move(args));
   WrapInFunction(tc);
@@ -1932,15 +1938,15 @@
   // matNxM<f32>(vecM<u32>(), ...); with N arguments
 
   const auto param = GetParam();
-  auto matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto* vec_type = create<sem::Vector>(ty.u32(), param.rows);
 
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns; i++) {
+    auto vec_type = ty.vec<u32>(param.rows);
     args.push_back(create<ast::TypeConstructorExpression>(
         Source{{12, i}}, vec_type, ExprList()));
   }
 
+  auto matrix_type = ty.mat<f32>(param.columns, param.rows);
   auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
                                                     std::move(args));
   WrapInFunction(tc);
@@ -1968,15 +1974,15 @@
   // matNxM<f32>(vecM<f32>(), ...); with N arguments
 
   const auto param = GetParam();
-  auto matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto vec_type = ty.vec<f32>(param.rows);
 
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns; i++) {
+    auto vec_type = ty.vec<f32>(param.rows);
     args.push_back(create<ast::TypeConstructorExpression>(
         Source{{12, i}}, vec_type, ExprList()));
   }
 
+  auto matrix_type = ty.mat<f32>(param.columns, param.rows);
   auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
                                                     std::move(args));
   WrapInFunction(tc);
@@ -1989,15 +1995,16 @@
 
   const auto param = GetParam();
   auto f32_alias = ty.alias("Float32", ty.f32());
-  auto matrix_type = ty.mat(f32_alias, param.columns, param.rows);
-  auto* vec_type = create<sem::Vector>(ty.u32(), param.rows);
+  AST().AddConstructedType(f32_alias);
 
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns; i++) {
+    auto vec_type = ty.vec(ty.u32(), param.rows);
     args.push_back(create<ast::TypeConstructorExpression>(
         Source{{12, i}}, vec_type, ExprList()));
   }
 
+  auto matrix_type = ty.mat(f32_alias, param.columns, param.rows);
   auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
                                                     std::move(args));
   WrapInFunction(tc);
@@ -2014,15 +2021,16 @@
 
   const auto param = GetParam();
   auto f32_alias = ty.alias("Float32", ty.f32());
-  auto matrix_type = ty.mat(f32_alias, param.columns, param.rows);
-  auto vec_type = ty.vec<f32>(param.rows);
+  AST().AddConstructedType(f32_alias);
 
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns; i++) {
+    auto vec_type = ty.vec<f32>(param.rows);
     args.push_back(create<ast::TypeConstructorExpression>(
         Source{{12, i}}, vec_type, ExprList()));
   }
 
+  auto matrix_type = ty.mat(f32_alias, param.columns, param.rows);
   auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
                                                     std::move(args));
   WrapInFunction(tc);
@@ -2031,9 +2039,10 @@
 }
 
 TEST_F(ResolverValidationTest, Expr_MatrixConstructor_ArgumentTypeAlias_Error) {
-  auto vec2_alias = ty.alias("VectorUnsigned2", ty.vec2<u32>());
+  auto alias = ty.alias("VectorUnsigned2", ty.vec2<u32>());
+  AST().AddConstructedType(alias);
   auto* tc = mat2x2<f32>(create<ast::TypeConstructorExpression>(
-                             Source{{12, 34}}, vec2_alias, ExprList()),
+                             Source{{12, 34}}, alias, ExprList()),
                          vec2<f32>());
   WrapInFunction(tc);
 
@@ -2048,6 +2057,7 @@
   auto matrix_type = ty.mat<f32>(param.columns, param.rows);
   auto vec_type = ty.vec<f32>(param.rows);
   auto vec_alias = ty.alias("VectorFloat2", vec_type);
+  AST().AddConstructedType(vec_alias);
 
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns; i++) {
@@ -2066,10 +2076,11 @@
   const auto param = GetParam();
   auto matrix_type = ty.mat<f32>(param.columns, param.rows);
   auto f32_alias = ty.alias("UnsignedInt", ty.u32());
-  auto* vec_type = create<sem::Vector>(f32_alias, param.rows);
+  AST().AddConstructedType(f32_alias);
 
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns; i++) {
+    auto vec_type = ty.vec(f32_alias, param.rows);
     args.push_back(create<ast::TypeConstructorExpression>(
         Source{{12, i}}, vec_type, ExprList()));
   }
@@ -2088,16 +2099,17 @@
 TEST_P(MatrixConstructorTest,
        Expr_Constructor_ArgumentElementTypeAlias_Success) {
   const auto param = GetParam();
-  auto matrix_type = ty.mat<f32>(param.columns, param.rows);
   auto f32_alias = ty.alias("Float32", ty.f32());
-  auto* vec_type = create<sem::Vector>(f32_alias, param.rows);
+  AST().AddConstructedType(f32_alias);
 
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns; i++) {
+    auto vec_type = ty.vec(f32_alias, param.rows);
     args.push_back(create<ast::TypeConstructorExpression>(
         Source{{12, i}}, vec_type, ExprList()));
   }
 
+  auto matrix_type = ty.mat<f32>(param.columns, param.rows);
   auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
                                                     std::move(args));
   WrapInFunction(tc);
diff --git a/src/writer/hlsl/generator_impl_function_test.cc b/src/writer/hlsl/generator_impl_function_test.cc
index 3292320..e107792 100644
--- a/src/writer/hlsl/generator_impl_function_test.cc
+++ b/src/writer/hlsl/generator_impl_function_test.cc
@@ -408,9 +408,9 @@
                      },
                      {create<ast::StructBlockDecoration>()});
 
-  sem::AccessControl ac(ast::AccessControl::kReadWrite, s);
+  auto ac = ty.access(ast::AccessControl::kReadWrite, s);
 
-  Global("coord", &ac, ast::StorageClass::kStorage, nullptr,
+  Global("coord", ac, ast::StorageClass::kStorage, nullptr,
          {
              create<ast::BindingDecoration>(0),
              create<ast::GroupDecoration>(1),
@@ -454,9 +454,9 @@
                      },
                      {create<ast::StructBlockDecoration>()});
 
-  sem::AccessControl ac(ast::AccessControl::kReadOnly, s);
+  auto ac = ty.access(ast::AccessControl::kReadOnly, s);
 
-  Global("coord", &ac, ast::StorageClass::kStorage, nullptr,
+  Global("coord", ac, ast::StorageClass::kStorage, nullptr,
          {
              create<ast::BindingDecoration>(0),
              create<ast::GroupDecoration>(1),
@@ -500,9 +500,9 @@
                      },
                      {create<ast::StructBlockDecoration>()});
 
-  sem::AccessControl ac(ast::AccessControl::kWriteOnly, s);
+  auto ac = ty.access(ast::AccessControl::kWriteOnly, s);
 
-  Global("coord", &ac, ast::StorageClass::kStorage, nullptr,
+  Global("coord", ac, ast::StorageClass::kStorage, nullptr,
          {
              create<ast::BindingDecoration>(0),
              create<ast::GroupDecoration>(1),
@@ -543,9 +543,9 @@
                      },
                      {create<ast::StructBlockDecoration>()});
 
-  sem::AccessControl ac(ast::AccessControl::kReadWrite, s);
+  auto ac = ty.access(ast::AccessControl::kReadWrite, s);
 
-  Global("coord", &ac, ast::StorageClass::kStorage, nullptr,
+  Global("coord", ac, ast::StorageClass::kStorage, nullptr,
          {
              create<ast::BindingDecoration>(0),
              create<ast::GroupDecoration>(1),
@@ -984,9 +984,9 @@
   auto s = Structure("Data", {Member("d", ty.f32())},
                      {create<ast::StructBlockDecoration>()});
 
-  sem::AccessControl ac(ast::AccessControl::kReadWrite, s);
+  auto ac = ty.access(ast::AccessControl::kReadWrite, s);
 
-  Global("data", &ac, ast::StorageClass::kStorage, nullptr,
+  Global("data", ac, ast::StorageClass::kStorage, nullptr,
          {
              create<ast::BindingDecoration>(0),
              create<ast::GroupDecoration>(0),
diff --git a/src/writer/hlsl/generator_impl_member_accessor_test.cc b/src/writer/hlsl/generator_impl_member_accessor_test.cc
index 8ff9211..515127b 100644
--- a/src/writer/hlsl/generator_impl_member_accessor_test.cc
+++ b/src/writer/hlsl/generator_impl_member_accessor_test.cc
@@ -32,7 +32,7 @@
   return ty.i32();
 }
 inline typ::Type ty_u32(const ProgramBuilder::TypesBuilder& ty) {
-  return ty.builder->create<sem::U32>();
+  return ty.u32();
 }
 inline typ::Type ty_f32(const ProgramBuilder::TypesBuilder& ty) {
   return ty.f32();
diff --git a/src/writer/msl/generator_impl_function_test.cc b/src/writer/msl/generator_impl_function_test.cc
index 687ca70..8a20007 100644
--- a/src/writer/msl/generator_impl_function_test.cc
+++ b/src/writer/msl/generator_impl_function_test.cc
@@ -307,9 +307,9 @@
                      },
                      {create<ast::StructBlockDecoration>()});
 
-  sem::AccessControl ac(ast::AccessControl::kReadWrite, s);
+  auto ac = ty.access(ast::AccessControl::kReadWrite, s);
 
-  Global("coord", &ac, ast::StorageClass::kStorage, nullptr,
+  Global("coord", ac, ast::StorageClass::kStorage, nullptr,
          {create<ast::BindingDecoration>(0), create<ast::GroupDecoration>(1)});
 
   auto* var = Var("v", ty.f32(), ast::StorageClass::kFunction,
@@ -352,9 +352,9 @@
                      },
                      {create<ast::StructBlockDecoration>()});
 
-  sem::AccessControl ac(ast::AccessControl::kReadOnly, s);
+  auto ac = ty.access(ast::AccessControl::kReadOnly, s);
 
-  Global("coord", &ac, ast::StorageClass::kStorage, nullptr,
+  Global("coord", ac, ast::StorageClass::kStorage, nullptr,
          {create<ast::BindingDecoration>(0), create<ast::GroupDecoration>(1)});
 
   auto* var = Var("v", ty.f32(), ast::StorageClass::kFunction,
@@ -608,9 +608,9 @@
                      },
                      {create<ast::StructBlockDecoration>()});
 
-  sem::AccessControl ac(ast::AccessControl::kReadWrite, s);
+  auto ac = ty.access(ast::AccessControl::kReadWrite, s);
 
-  Global("coord", &ac, ast::StorageClass::kStorage, nullptr,
+  Global("coord", ac, ast::StorageClass::kStorage, nullptr,
          {create<ast::BindingDecoration>(0), create<ast::GroupDecoration>(1)});
 
   ast::VariableList params;
@@ -664,9 +664,9 @@
                      },
                      {create<ast::StructBlockDecoration>()});
 
-  sem::AccessControl ac(ast::AccessControl::kReadOnly, s);
+  auto ac = ty.access(ast::AccessControl::kReadOnly, s);
 
-  Global("coord", &ac, ast::StorageClass::kStorage, nullptr,
+  Global("coord", ac, ast::StorageClass::kStorage, nullptr,
          {create<ast::BindingDecoration>(0), create<ast::GroupDecoration>(1)});
 
   ast::VariableList params;
@@ -799,9 +799,9 @@
   auto s = Structure("Data", {Member("d", ty.f32())},
                      {create<ast::StructBlockDecoration>()});
 
-  sem::AccessControl ac(ast::AccessControl::kReadWrite, s);
+  auto ac = ty.access(ast::AccessControl::kReadWrite, s);
 
-  Global("data", &ac, ast::StorageClass::kStorage, nullptr,
+  Global("data", ac, ast::StorageClass::kStorage, nullptr,
          {create<ast::BindingDecoration>(0), create<ast::GroupDecoration>(0)});
 
   {
diff --git a/src/writer/msl/generator_impl_variable_decl_statement_test.cc b/src/writer/msl/generator_impl_variable_decl_statement_test.cc
index 352ae5a..1f14790 100644
--- a/src/writer/msl/generator_impl_variable_decl_statement_test.cc
+++ b/src/writer/msl/generator_impl_variable_decl_statement_test.cc
@@ -52,9 +52,7 @@
 }
 
 TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Array) {
-  sem::ArrayType ary(ty.f32(), 5, ast::DecorationList{});
-
-  auto* var = Var("a", &ary, ast::StorageClass::kNone);
+  auto* var = Var("a", ty.array<f32, 5>(), ast::StorageClass::kNone);
   auto* stmt = Decl(var);
   WrapInFunction(stmt);
 
diff --git a/src/writer/spirv/builder_accessor_expression_test.cc b/src/writer/spirv/builder_accessor_expression_test.cc
index 4c50c9c..adcb694 100644
--- a/src/writer/spirv/builder_accessor_expression_test.cc
+++ b/src/writer/spirv/builder_accessor_expression_test.cc
@@ -754,12 +754,10 @@
   //   vec2<f32>(0.5, -0.5));
   // pos[1]
 
-  auto arr = ty.array(ty.vec2<f32>(), 3);
-
   auto* var =
-      GlobalConst("pos", arr,
-                  Construct(arr, vec2<f32>(0.0f, 0.5f), vec2<f32>(-0.5f, -0.5f),
-                            vec2<f32>(0.5f, -0.5f)));
+      GlobalConst("pos", ty.array(ty.vec2<f32>(), 3),
+                  Construct(ty.array(ty.vec2<f32>(), 3), vec2<f32>(0.0f, 0.5f),
+                            vec2<f32>(-0.5f, -0.5f), vec2<f32>(0.5f, -0.5f)));
 
   auto* expr = IndexAccessor("pos", 1u);
   WrapInFunction(expr);
diff --git a/src/writer/spirv/builder_constructor_expression_test.cc b/src/writer/spirv/builder_constructor_expression_test.cc
index 6b25bf3..463246f 100644
--- a/src/writer/spirv/builder_constructor_expression_test.cc
+++ b/src/writer/spirv/builder_constructor_expression_test.cc
@@ -94,6 +94,7 @@
   // cast<Int>(2.3f)
 
   auto alias = ty.alias("Int", ty.i32());
+  AST().AddConstructedType(alias);
   auto* cast = Construct(alias, 2.3f);
   WrapInFunction(cast);
 
diff --git a/src/writer/spirv/builder_entry_point_test.cc b/src/writer/spirv/builder_entry_point_test.cc
index ea34eb1..5771b4e 100644
--- a/src/writer/spirv/builder_entry_point_test.cc
+++ b/src/writer/spirv/builder_entry_point_test.cc
@@ -42,12 +42,11 @@
   //              [[location(1)]] loc1 : f32) {
   //   var col : f32 = (coord.x * loc1);
   // }
-  auto f32 = ty.f32();
-  auto vec4 = ty.vec4<float>();
-  auto* coord = Param("coord", vec4, {Builtin(ast::Builtin::kPosition)});
-  auto* loc1 = Param("loc1", f32, {Location(1u)});
+  auto* coord =
+      Param("coord", ty.vec4<f32>(), {Builtin(ast::Builtin::kPosition)});
+  auto* loc1 = Param("loc1", ty.f32(), {Location(1u)});
   auto* mul = Mul(Expr(MemberAccessor("coord", "x")), Expr("loc1"));
-  auto* col = Var("col", f32, ast::StorageClass::kFunction, mul, {});
+  auto* col = Var("col", ty.f32(), ast::StorageClass::kFunction, mul, {});
   Func("frag_main", ast::VariableList{coord, loc1}, ty.void_(),
        ast::StatementList{WrapInStatement(col)},
        ast::DecorationList{
@@ -105,12 +104,10 @@
   //   }
   //   return 1.0;
   // }
-  auto f32 = ty.f32();
-  auto u32 = ty.u32();
-  auto* loc_in = Param("loc_in", u32, {Location(0)});
+  auto* loc_in = Param("loc_in", ty.u32(), {Location(0)});
   auto* cond = create<ast::BinaryExpression>(ast::BinaryOp::kGreaterThan,
                                              Expr("loc_in"), Expr(10u));
-  Func("frag_main", ast::VariableList{loc_in}, f32,
+  Func("frag_main", ast::VariableList{loc_in}, ty.f32(),
        ast::StatementList{
            If(cond, Block(Return(0.5f))),
            Return(1.0f),
diff --git a/src/writer/spirv/builder_function_test.cc b/src/writer/spirv/builder_function_test.cc
index 77b0866..cf717cc 100644
--- a/src/writer/spirv/builder_function_test.cc
+++ b/src/writer/spirv/builder_function_test.cc
@@ -204,9 +204,9 @@
   auto s = Structure("Data", {Member("d", ty.f32())},
                      {create<ast::StructBlockDecoration>()});
 
-  sem::AccessControl ac(ast::AccessControl::kReadWrite, s);
+  auto ac = ty.access(ast::AccessControl::kReadWrite, s);
 
-  Global("data", &ac, ast::StorageClass::kStorage, nullptr,
+  Global("data", ac, ast::StorageClass::kStorage, nullptr,
          ast::DecorationList{
              create<ast::BindingDecoration>(0),
              create<ast::GroupDecoration>(0),
diff --git a/src/writer/spirv/builder_global_variable_test.cc b/src/writer/spirv/builder_global_variable_test.cc
index 4917a1a..51a5b9d 100644
--- a/src/writer/spirv/builder_global_variable_test.cc
+++ b/src/writer/spirv/builder_global_variable_test.cc
@@ -495,11 +495,11 @@
 
   auto A = Structure("A", {Member("a", ty.i32())},
                      {create<ast::StructBlockDecoration>()});
-  sem::AccessControl read{ast::AccessControl::kReadOnly, A};
-  sem::AccessControl rw{ast::AccessControl::kReadWrite, A};
+  auto read = ty.access(ast::AccessControl::kReadOnly, A);
+  auto rw = ty.access(ast::AccessControl::kReadWrite, A);
 
-  auto* var_b = Global("b", &read, ast::StorageClass::kStorage);
-  auto* var_c = Global("c", &rw, ast::StorageClass::kStorage);
+  auto* var_b = Global("b", read, ast::StorageClass::kStorage);
+  auto* var_c = Global("c", rw, ast::StorageClass::kStorage);
 
   spirv::Builder& b = Build();
 
diff --git a/src/writer/spirv/builder_intrinsic_test.cc b/src/writer/spirv/builder_intrinsic_test.cc
index c5a63d0..a020a59 100644
--- a/src/writer/spirv/builder_intrinsic_test.cc
+++ b/src/writer/spirv/builder_intrinsic_test.cc
@@ -370,12 +370,12 @@
 
 // This tests that we do not push OpTypeSampledImage and float_0 type twice.
 TEST_F(IntrinsicBuilderTest, Call_TextureSampleCompare_Twice) {
-  sem::Sampler s(ast::SamplerKind::kComparisonSampler);
-  sem::DepthTexture t(ast::TextureDimension::k2d);
+  auto s = ty.sampler(ast::SamplerKind::kComparisonSampler);
+  auto t = ty.depth_texture(ast::TextureDimension::k2d);
 
-  auto* tex = Global("texture", &t, ast::StorageClass::kInput);
+  auto* tex = Global("texture", t, ast::StorageClass::kInput);
 
-  auto* sampler = Global("sampler", &s, ast::StorageClass::kInput);
+  auto* sampler = Global("sampler", s, ast::StorageClass::kInput);
 
   auto* expr1 = Call("textureSampleCompare", "texture", "sampler",
                      vec2<f32>(1.0f, 2.0f), 2.0f);
diff --git a/src/writer/wgsl/generator_impl_function_test.cc b/src/writer/wgsl/generator_impl_function_test.cc
index 0dffdec..1e829f0 100644
--- a/src/writer/wgsl/generator_impl_function_test.cc
+++ b/src/writer/wgsl/generator_impl_function_test.cc
@@ -205,9 +205,9 @@
   auto s = Structure("Data", {Member("d", ty.f32())},
                      {create<ast::StructBlockDecoration>()});
 
-  sem::AccessControl ac(ast::AccessControl::kReadWrite, s);
+  auto ac = ty.access(ast::AccessControl::kReadWrite, s);
 
-  Global("data", &ac, ast::StorageClass::kStorage, nullptr,
+  Global("data", ac, ast::StorageClass::kStorage, nullptr,
          ast::DecorationList{
              create<ast::BindingDecoration>(0),
              create<ast::GroupDecoration>(0),