Use ProgramBuilder::Construct() where possible

Replace all calls to create<ast::TypeConstructorExpression>() with
Construct(). TypeConstructorExpression will be folded into
ast::CallExpression, but the Construct() call signature will remain
identical.

Bug: tint:888
Change-Id: Ifb28a90ccf5184c8090c2e32fa8c82f3996dfa33
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/69108
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc
index 08db5f4..d987039 100644
--- a/src/reader/spirv/function.cc
+++ b/src/reader/spirv/function.cc
@@ -1350,8 +1350,8 @@
 
       // Add the return-value statement.
       stmts.push_back(create<ast::ReturnStatement>(
-          source, create<ast::TypeConstructorExpression>(
-                      source, return_type, std::move(return_exprs))));
+          source,
+          builder_.Construct(source, return_type, std::move(return_exprs))));
     }
   }
 
@@ -3960,9 +3960,8 @@
     for (uint32_t iarg = 0; iarg < inst.NumInOperands(); ++iarg) {
       operands.emplace_back(MakeOperand(inst, iarg).expr);
     }
-    return {ast_type,
-            create<ast::TypeConstructorExpression>(
-                Source{}, ast_type->Build(builder_), std::move(operands))};
+    return {ast_type, builder_.Construct(Source{}, ast_type->Build(builder_),
+                                         std::move(operands))};
   }
 
   if (opcode == SpvOpCompositeExtract) {
@@ -4646,8 +4645,8 @@
       return {};
     }
   }
-  return {result_type, create<ast::TypeConstructorExpression>(
-                           source, result_type->Build(builder_), values)};
+  return {result_type,
+          builder_.Construct(source, result_type->Build(builder_), values)};
 }
 
 bool FunctionEmitter::RegisterSpecialBuiltInVariables() {
@@ -5018,10 +5017,10 @@
 
   ast::ExpressionList params;
   params.push_back(arg_expr.expr);
-  TypedExpression result{expr_type,
-                         create<ast::TypeConstructorExpression>(
-                             GetSourceForInst(inst), expr_type->Build(builder_),
-                             std::move(params))};
+  TypedExpression result{
+      expr_type,
+      builder_.Construct(GetSourceForInst(inst), expr_type->Build(builder_),
+                         std::move(params))};
 
   if (requested_type == expr_type) {
     return result;
@@ -5468,7 +5467,7 @@
     // first component.
     if (texture_type->IsAnyOf<DepthTexture, DepthMultisampledTexture>()) {
       if (is_non_dref_sample || (opcode == SpvOpImageFetch)) {
-        value = create<ast::TypeConstructorExpression>(
+        value = builder_.Construct(
             Source{},
             result_type->Build(builder_),  // a vec4
             ast::ExpressionList{
@@ -5555,8 +5554,8 @@
       }
       auto* result_type = parser_impl_.ConvertType(inst.type_id());
       TypedExpression expr = {
-          result_type, create<ast::TypeConstructorExpression>(
-                           Source{}, result_type->Build(builder_), exprs)};
+          result_type,
+          builder_.Construct(Source{}, result_type->Build(builder_), exprs)};
       return EmitConstDefOrWriteToHoistedVar(inst, expr);
     }
     case SpvOpImageQueryLod:
@@ -5577,9 +5576,8 @@
       // The SPIR-V result type must be integer scalar. The WGSL bulitin
       // returns i32. If they aren't the same then convert the result.
       if (!result_type->Is<I32>()) {
-        ast_expr = create<ast::TypeConstructorExpression>(
-            Source{}, result_type->Build(builder_),
-            ast::ExpressionList{ast_expr});
+        ast_expr = builder_.Construct(Source{}, result_type->Build(builder_),
+                                      ast::ExpressionList{ast_expr});
       }
       TypedExpression expr{result_type, ast_expr};
       return EmitConstDefOrWriteToHoistedVar(inst, expr);
@@ -5784,8 +5782,8 @@
     for (auto i = src_count; i < dest_count; i++) {
       exprs.push_back(parser_impl_.MakeNullExpression(component_type).expr);
     }
-    texel.expr = create<ast::TypeConstructorExpression>(
-        Source{}, texel.type->Build(builder_), std::move(exprs));
+    texel.expr = builder_.Construct(Source{}, texel.type->Build(builder_),
+                                    std::move(exprs));
   }
 
   return texel.expr;
@@ -5795,9 +5793,8 @@
   if (!value || value.type->Is<I32>()) {
     return value;
   }
-  return {ty_.I32(),
-          create<ast::TypeConstructorExpression>(
-              Source{}, builder_.ty.i32(), ast::ExpressionList{value.expr})};
+  return {ty_.I32(), builder_.Construct(Source{}, builder_.ty.i32(),
+                                        ast::ExpressionList{value.expr})};
 }
 
 TypedExpression FunctionEmitter::ToSignedIfUnsigned(TypedExpression value) {
@@ -5890,11 +5887,11 @@
           Source{}, ast::BinaryOp::kMultiply, row_factor, column_factor);
       result_row.push_back(elem);
     }
-    result_columns.push_back(create<ast::TypeConstructorExpression>(
-        Source{}, col_ty->Build(builder_), result_row));
+    result_columns.push_back(
+        builder_.Construct(Source{}, col_ty->Build(builder_), result_row));
   }
-  return {result_ty, create<ast::TypeConstructorExpression>(
-                         Source{}, result_ty->Build(builder_), result_columns)};
+  return {result_ty, builder_.Construct(Source{}, result_ty->Build(builder_),
+                                        result_columns)};
 }
 
 bool FunctionEmitter::MakeVectorInsertDynamic(
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index 252a2ff..a6fc0f4 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -1862,9 +1862,9 @@
     auto y = MakeConstantExpression(workgroup_size_builtin_.y_id);
     auto z = MakeConstantExpression(workgroup_size_builtin_.z_id);
     auto* ast_type = ty_.Vector(x.type, 3);
-    return {ast_type, create<ast::TypeConstructorExpression>(
-                          Source{}, ast_type->Build(builder_),
-                          ast::ExpressionList{x.expr, y.expr, z.expr})};
+    return {ast_type,
+            builder_.Construct(Source{}, ast_type->Build(builder_),
+                               ast::ExpressionList{x.expr, y.expr, z.expr})};
   } else if (id == workgroup_size_builtin_.x_id) {
     return MakeConstantExpressionForScalarSpirvConstant(
         Source{}, ConvertType(workgroup_size_builtin_.component_type_id),
@@ -1933,9 +1933,9 @@
         // We've already emitted a diagnostic.
         return {};
       }
-      return {original_ast_type, create<ast::TypeConstructorExpression>(
-                                     source, original_ast_type->Build(builder_),
-                                     std::move(ast_components))};
+      return {original_ast_type,
+              builder_.Construct(source, original_ast_type->Build(builder_),
+                                 std::move(ast_components))};
     }
     default:
       break;
@@ -2005,16 +2005,16 @@
   if (type->Is<Alias>()) {
     // TODO(amaiorano): No type constructor for TypeName (yet?)
     ast::ExpressionList ast_components;
-    return create<ast::TypeConstructorExpression>(
-        Source{}, original_type->Build(builder_), std::move(ast_components));
+    return builder_.Construct(Source{}, original_type->Build(builder_),
+                              std::move(ast_components));
   }
   if (auto* vec_ty = type->As<Vector>()) {
     ast::ExpressionList ast_components;
     for (size_t i = 0; i < vec_ty->size; ++i) {
       ast_components.emplace_back(MakeNullValue(vec_ty->type));
     }
-    return create<ast::TypeConstructorExpression>(
-        Source{}, type->Build(builder_), std::move(ast_components));
+    return builder_.Construct(Source{}, type->Build(builder_),
+                              std::move(ast_components));
   }
   if (auto* mat_ty = type->As<Matrix>()) {
     // Matrix components are columns
@@ -2023,24 +2023,24 @@
     for (size_t i = 0; i < mat_ty->columns; ++i) {
       ast_components.emplace_back(MakeNullValue(column_ty));
     }
-    return create<ast::TypeConstructorExpression>(
-        Source{}, type->Build(builder_), std::move(ast_components));
+    return builder_.Construct(Source{}, type->Build(builder_),
+                              std::move(ast_components));
   }
   if (auto* arr_ty = type->As<Array>()) {
     ast::ExpressionList ast_components;
     for (size_t i = 0; i < arr_ty->size; ++i) {
       ast_components.emplace_back(MakeNullValue(arr_ty->type));
     }
-    return create<ast::TypeConstructorExpression>(
-        Source{}, original_type->Build(builder_), std::move(ast_components));
+    return builder_.Construct(Source{}, original_type->Build(builder_),
+                              std::move(ast_components));
   }
   if (auto* struct_ty = type->As<Struct>()) {
     ast::ExpressionList ast_components;
     for (auto* member : struct_ty->members) {
       ast_components.emplace_back(MakeNullValue(member));
     }
-    return create<ast::TypeConstructorExpression>(
-        Source{}, original_type->Build(builder_), std::move(ast_components));
+    return builder_.Construct(Source{}, original_type->Build(builder_),
+                              std::move(ast_components));
   }
   Fail() << "can't make null value for type: " << type->TypeInfo().name;
   return nullptr;
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index 77df7ed..28e9cf0 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -2232,8 +2232,7 @@
     if (params.errored)
       return Failure::kErrored;
 
-    return create<ast::TypeConstructorExpression>(source, type.value,
-                                                  std::move(params.value));
+    return builder_.Construct(source, type.value, std::move(params.value));
   }
 
   return Failure::kNoMatch;
@@ -2917,8 +2916,7 @@
       if (params.errored)
         return Failure::kErrored;
 
-      return create<ast::TypeConstructorExpression>(source, type.value,
-                                                    params.value);
+      return builder_.Construct(source, type.value, params.value);
     }
   }
   return add_error(peek(), "unable to parse const_expr");
diff --git a/src/resolver/type_constructor_validation_test.cc b/src/resolver/type_constructor_validation_test.cc
index 10d86e5..aa81cf6 100644
--- a/src/resolver/type_constructor_validation_test.cc
+++ b/src/resolver/type_constructor_validation_test.cc
@@ -471,8 +471,7 @@
        Expr_Constructor_Array_ScalarArgumentTypeMismatch_Vec2) {
   // array<i32, 3>(1, vec2<i32>());
   auto* tc =
-      array<i32, 3>(Expr(1), create<ast::TypeConstructorExpression>(
-                                 Source{{12, 34}}, ty.vec2<i32>(), ExprList()));
+      array<i32, 3>(Expr(1), Construct(Source{{12, 34}}, ty.vec2<i32>()));
   WrapInFunction(tc);
   EXPECT_FALSE(r()->Resolve());
   EXPECT_EQ(r()->error(),
@@ -636,8 +635,7 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec2_Error_Vec3ArgumentCardinalityTooLarge) {
-  auto* tc = vec2<f32>(create<ast::TypeConstructorExpression>(
-      Source{{12, 34}}, ty.vec3<f32>(), ExprList()));
+  auto* tc = vec2<f32>(Construct(Source{{12, 34}}, ty.vec3<f32>()));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -648,8 +646,7 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec2_Error_Vec4ArgumentCardinalityTooLarge) {
-  auto* tc = vec2<f32>(create<ast::TypeConstructorExpression>(
-      Source{{12, 34}}, ty.vec4<f32>(), ExprList()));
+  auto* tc = vec2<f32>(Construct(Source{{12, 34}}, ty.vec4<f32>()));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -673,10 +670,8 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec2_Error_TooManyArgumentsVector) {
-  auto* tc = vec2<f32>(create<ast::TypeConstructorExpression>(
-                           Source{{12, 34}}, ty.vec2<f32>(), ExprList()),
-                       create<ast::TypeConstructorExpression>(
-                           Source{{12, 40}}, ty.vec2<f32>(), ExprList()));
+  auto* tc = vec2<f32>(Construct(Source{{12, 34}}, ty.vec2<f32>()),
+                       Construct(Source{{12, 40}}, ty.vec2<f32>()));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -687,8 +682,7 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec2_Error_TooManyArgumentsVectorAndScalar) {
-  auto* tc = vec2<f32>(create<ast::TypeConstructorExpression>(
-                           Source{{12, 34}}, ty.vec2<f32>(), ExprList()),
+  auto* tc = vec2<f32>(Construct(Source{{12, 34}}, ty.vec2<f32>()),
                        Expr(Source{{12, 40}}, 1.0f));
   WrapInFunction(tc);
 
@@ -700,8 +694,7 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec2_Error_InvalidArgumentType) {
-  auto* tc = vec2<f32>(create<ast::TypeConstructorExpression>(
-      Source{{12, 34}}, ty.mat2x2<f32>(), ExprList()));
+  auto* tc = vec2<f32>(Construct(Source{{12, 34}}, ty.mat2x2<f32>()));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -847,8 +840,7 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec3_Error_Vec4ArgumentCardinalityTooLarge) {
-  auto* tc = vec3<f32>(create<ast::TypeConstructorExpression>(
-      Source{{12, 34}}, ty.vec4<f32>(), ExprList()));
+  auto* tc = vec3<f32>(Construct(Source{{12, 34}}, ty.vec4<f32>()));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -884,8 +876,7 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec3_Error_TooFewArgumentsVec2) {
-  auto* tc = vec3<f32>(create<ast::TypeConstructorExpression>(
-      Source{{12, 34}}, ty.vec2<f32>(), ExprList()));
+  auto* tc = vec3<f32>(Construct(Source{{12, 34}}, ty.vec2<f32>()));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -896,10 +887,8 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec3_Error_TooManyArgumentsVec2) {
-  auto* tc = vec3<f32>(create<ast::TypeConstructorExpression>(
-                           Source{{12, 34}}, ty.vec2<f32>(), ExprList()),
-                       create<ast::TypeConstructorExpression>(
-                           Source{{12, 40}}, ty.vec2<f32>(), ExprList()));
+  auto* tc = vec3<f32>(Construct(Source{{12, 34}}, ty.vec2<f32>()),
+                       Construct(Source{{12, 40}}, ty.vec2<f32>()));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -911,8 +900,7 @@
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec3_Error_TooManyArgumentsVec2AndScalar) {
   auto* tc =
-      vec3<f32>(create<ast::TypeConstructorExpression>(
-                    Source{{12, 34}}, ty.vec2<f32>(), ExprList()),
+      vec3<f32>(Construct(Source{{12, 34}}, ty.vec2<f32>()),
                 Expr(Source{{12, 40}}, 1.0f), Expr(Source{{12, 46}}, 1.0f));
   WrapInFunction(tc);
 
@@ -924,8 +912,7 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec3_Error_TooManyArgumentsVec3) {
-  auto* tc = vec3<f32>(create<ast::TypeConstructorExpression>(
-                           Source{{12, 34}}, ty.vec3<f32>(), ExprList()),
+  auto* tc = vec3<f32>(Construct(Source{{12, 34}}, ty.vec3<f32>()),
                        Expr(Source{{12, 40}}, 1.0f));
   WrapInFunction(tc);
 
@@ -937,8 +924,7 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec3_Error_InvalidArgumentType) {
-  auto* tc = vec3<f32>(create<ast::TypeConstructorExpression>(
-      Source{{12, 34}}, ty.mat2x2<f32>(), ExprList()));
+  auto* tc = vec3<f32>(Construct(Source{{12, 34}}, ty.mat2x2<f32>()));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1137,8 +1123,7 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec4_Error_TooFewArgumentsVec2AndScalar) {
-  auto* tc = vec4<f32>(create<ast::TypeConstructorExpression>(
-                           Source{{12, 34}}, ty.vec2<f32>(), ExprList()),
+  auto* tc = vec4<f32>(Construct(Source{{12, 34}}, ty.vec2<f32>()),
                        Expr(Source{{12, 40}}, 1.0f));
   WrapInFunction(tc);
 
@@ -1150,11 +1135,9 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec4_Error_TooManyArgumentsVec2AndScalars) {
-  auto* tc =
-      vec4<f32>(create<ast::TypeConstructorExpression>(
-                    Source{{12, 34}}, ty.vec2<f32>(), ExprList()),
-                Expr(Source{{12, 40}}, 1.0f), Expr(Source{{12, 46}}, 1.0f),
-                Expr(Source{{12, 52}}, 1.0f));
+  auto* tc = vec4<f32>(
+      Construct(Source{{12, 34}}, ty.vec2<f32>()), Expr(Source{{12, 40}}, 1.0f),
+      Expr(Source{{12, 46}}, 1.0f), Expr(Source{{12, 52}}, 1.0f));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1165,10 +1148,8 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec4_Error_TooManyArgumentsVec2Vec2Scalar) {
-  auto* tc = vec4<f32>(create<ast::TypeConstructorExpression>(
-                           Source{{12, 34}}, ty.vec2<f32>(), ExprList()),
-                       create<ast::TypeConstructorExpression>(
-                           Source{{12, 40}}, ty.vec2<f32>(), ExprList()),
+  auto* tc = vec4<f32>(Construct(Source{{12, 34}}, ty.vec2<f32>()),
+                       Construct(Source{{12, 40}}, ty.vec2<f32>()),
                        Expr(Source{{12, 46}}, 1.0f));
   WrapInFunction(tc);
 
@@ -1180,12 +1161,9 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec4_Error_TooManyArgumentsVec2Vec2Vec2) {
-  auto* tc = vec4<f32>(create<ast::TypeConstructorExpression>(
-                           Source{{12, 34}}, ty.vec2<f32>(), ExprList()),
-                       create<ast::TypeConstructorExpression>(
-                           Source{{12, 40}}, ty.vec2<f32>(), ExprList()),
-                       create<ast::TypeConstructorExpression>(
-                           Source{{12, 40}}, ty.vec2<f32>(), ExprList()));
+  auto* tc = vec4<f32>(Construct(Source{{12, 34}}, ty.vec2<f32>()),
+                       Construct(Source{{12, 40}}, ty.vec2<f32>()),
+                       Construct(Source{{12, 40}}, ty.vec2<f32>()));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1196,8 +1174,7 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec4_Error_TooFewArgumentsVec3) {
-  auto* tc = vec4<f32>(create<ast::TypeConstructorExpression>(
-      Source{{12, 34}}, ty.vec3<f32>(), ExprList()));
+  auto* tc = vec4<f32>(Construct(Source{{12, 34}}, ty.vec3<f32>()));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1209,8 +1186,7 @@
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec4_Error_TooManyArgumentsVec3AndScalars) {
   auto* tc =
-      vec4<f32>(create<ast::TypeConstructorExpression>(
-                    Source{{12, 34}}, ty.vec3<f32>(), ExprList()),
+      vec4<f32>(Construct(Source{{12, 34}}, ty.vec3<f32>()),
                 Expr(Source{{12, 40}}, 1.0f), Expr(Source{{12, 46}}, 1.0f));
   WrapInFunction(tc);
 
@@ -1222,10 +1198,8 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec4_Error_TooManyArgumentsVec3AndVec2) {
-  auto* tc = vec4<f32>(create<ast::TypeConstructorExpression>(
-                           Source{{12, 34}}, ty.vec3<f32>(), ExprList()),
-                       create<ast::TypeConstructorExpression>(
-                           Source{{12, 40}}, ty.vec2<f32>(), ExprList()));
+  auto* tc = vec4<f32>(Construct(Source{{12, 34}}, ty.vec3<f32>()),
+                       Construct(Source{{12, 40}}, ty.vec2<f32>()));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1236,10 +1210,8 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec4_Error_TooManyArgumentsVec2AndVec3) {
-  auto* tc = vec4<f32>(create<ast::TypeConstructorExpression>(
-                           Source{{12, 34}}, ty.vec2<f32>(), ExprList()),
-                       create<ast::TypeConstructorExpression>(
-                           Source{{12, 40}}, ty.vec3<f32>(), ExprList()));
+  auto* tc = vec4<f32>(Construct(Source{{12, 34}}, ty.vec2<f32>()),
+                       Construct(Source{{12, 40}}, ty.vec3<f32>()));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1250,10 +1222,8 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec4_Error_TooManyArgumentsVec3AndVec3) {
-  auto* tc = vec4<f32>(create<ast::TypeConstructorExpression>(
-                           Source{{12, 34}}, ty.vec3<f32>(), ExprList()),
-                       create<ast::TypeConstructorExpression>(
-                           Source{{12, 40}}, ty.vec3<f32>(), ExprList()));
+  auto* tc = vec4<f32>(Construct(Source{{12, 34}}, ty.vec3<f32>()),
+                       Construct(Source{{12, 40}}, ty.vec3<f32>()));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1264,8 +1234,7 @@
 
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_Constructor_Vec4_Error_InvalidArgumentType) {
-  auto* tc = vec4<f32>(create<ast::TypeConstructorExpression>(
-      Source{{12, 34}}, ty.mat2x2<f32>(), ExprList()));
+  auto* tc = vec4<f32>(Construct(Source{{12, 34}}, ty.mat2x2<f32>()));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1502,8 +1471,8 @@
 
   // vec2<Float32>(1.0f, 1u)
   auto* vec_type = ty.vec(ty.Of(f32_alias), 2);
-  auto* tc = create<ast::TypeConstructorExpression>(
-      Source{{12, 34}}, vec_type, ExprList(1.0f, Expr(Source{{12, 40}}, 1u)));
+  auto* tc =
+      Construct(Source{{12, 34}}, vec_type, 1.0f, Expr(Source{{12, 40}}, 1u));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1518,8 +1487,7 @@
 
   // vec2<Float32>(1.0f, 1.0f)
   auto* vec_type = ty.vec(ty.Of(f32_alias), 2);
-  auto* tc = create<ast::TypeConstructorExpression>(Source{{12, 34}}, vec_type,
-                                                    ExprList(1.0f, 1.0f));
+  auto* tc = Construct(Source{{12, 34}}, vec_type, 1.0f, 1.0f);
   WrapInFunction(tc);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1531,9 +1499,7 @@
 
   // vec3<u32>(vec<Float32>(), 1.0f)
   auto* vec_type = ty.vec(ty.Of(f32_alias), 2);
-  auto* tc = vec3<u32>(create<ast::TypeConstructorExpression>(
-                           Source{{12, 34}}, vec_type, ExprList()),
-                       1.0f);
+  auto* tc = vec3<u32>(Construct(Source{{12, 34}}, vec_type), 1.0f);
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1548,9 +1514,7 @@
 
   // vec3<f32>(vec<Float32>(), 1.0f)
   auto* vec_type = ty.vec(ty.Of(f32_alias), 2);
-  auto* tc = vec3<f32>(create<ast::TypeConstructorExpression>(
-                           Source{{12, 34}}, vec_type, ExprList()),
-                       1.0f);
+  auto* tc = vec3<f32>(Construct(Source{{12, 34}}, vec_type), 1.0f);
   WrapInFunction(tc);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1579,13 +1543,11 @@
   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()));
+    args.push_back(Construct(Source{{12, i}}, vec_type));
   }
 
   auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
-                                                    std::move(args));
+  auto* tc = Construct(Source{}, matrix_type, std::move(args));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1601,13 +1563,11 @@
 
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns * param.rows - 1; i++) {
-    args.push_back(create<ast::TypeConstructorExpression>(
-        Source{{12, i}}, ty.f32(), ExprList()));
+    args.push_back(Construct(Source{{12, i}}, ty.f32()));
   }
 
   auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
-                                                    std::move(args));
+  auto* tc = Construct(Source{}, matrix_type, std::move(args));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1624,13 +1584,11 @@
   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()));
+    args.push_back(Construct(Source{{12, i}}, vec_type));
   }
 
   auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
-                                                    std::move(args));
+  auto* tc = Construct(Source{}, matrix_type, std::move(args));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1646,13 +1604,11 @@
 
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns * param.rows + 1; i++) {
-    args.push_back(create<ast::TypeConstructorExpression>(
-        Source{{12, i}}, ty.f32(), ExprList()));
+    args.push_back(Construct(Source{{12, i}}, ty.f32()));
   }
 
   auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
-                                                    std::move(args));
+  auto* tc = Construct(Source{}, matrix_type, std::move(args));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1670,13 +1626,11 @@
   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()));
+    args.push_back(Construct(Source{{12, i}}, vec_type));
   }
 
   auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
-                                                    std::move(args));
+  auto* tc = Construct(Source{}, matrix_type, std::move(args));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1697,8 +1651,7 @@
   }
 
   auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
-                                                    std::move(args));
+  auto* tc = Construct(Source{}, matrix_type, std::move(args));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1721,17 +1674,14 @@
   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()));
+    args.push_back(Construct(Source{{12, i}}, valid_vec_type));
   }
   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()));
+  args.push_back(Construct(Source{{12, kInvalidLoc}}, invalid_vec_type));
 
   auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
-                                                    std::move(args));
+  auto* tc = Construct(Source{}, matrix_type, std::move(args));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1754,17 +1704,14 @@
   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()));
+    args.push_back(Construct(Source{{12, i}}, valid_vec_type));
   }
   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()));
+  args.push_back(Construct(Source{{12, kInvalidLoc}}, invalid_vec_type));
 
   auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
-                                                    std::move(args));
+  auto* tc = Construct(Source{}, matrix_type, std::move(args));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1778,8 +1725,7 @@
 
   const auto param = GetParam();
   auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto* tc = create<ast::TypeConstructorExpression>(Source{{12, 40}},
-                                                    matrix_type, ExprList());
+  auto* tc = Construct(Source{{12, 40}}, matrix_type);
   WrapInFunction(tc);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1793,13 +1739,11 @@
   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()));
+    args.push_back(Construct(Source{{12, i}}, vec_type));
   }
 
   auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
-                                                    std::move(args));
+  auto* tc = Construct(Source{}, matrix_type, std::move(args));
   WrapInFunction(tc);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1812,13 +1756,11 @@
 
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns * param.rows; i++) {
-    args.push_back(create<ast::TypeConstructorExpression>(
-        Source{{12, i}}, ty.f32(), ExprList()));
+    args.push_back(Construct(Source{{12, i}}, ty.f32()));
   }
 
   auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
-                                                    std::move(args));
+  auto* tc = Construct(Source{}, matrix_type, std::move(args));
   WrapInFunction(tc);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1833,13 +1775,11 @@
   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()));
+    args.push_back(Construct(Source{{12, i}}, vec_type));
   }
 
   auto* matrix_type = ty.mat(ty.Of(f32_alias), param.columns, param.rows);
-  auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
-                                                    std::move(args));
+  auto* tc = Construct(Source{}, matrix_type, std::move(args));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1857,13 +1797,11 @@
   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()));
+    args.push_back(Construct(Source{{12, i}}, vec_type));
   }
 
   auto* matrix_type = ty.mat(ty.Of(f32_alias), param.columns, param.rows);
-  auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
-                                                    std::move(args));
+  auto* tc = Construct(Source{}, matrix_type, std::move(args));
   WrapInFunction(tc);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1872,9 +1810,8 @@
 TEST_F(ResolverTypeConstructorValidationTest,
        Expr_MatrixConstructor_ArgumentTypeAlias_Error) {
   auto* alias = Alias("VectorUnsigned2", ty.vec2<u32>());
-  auto* tc = mat2x2<f32>(create<ast::TypeConstructorExpression>(
-                             Source{{12, 34}}, ty.Of(alias), ExprList()),
-                         vec2<f32>());
+  auto* tc =
+      mat2x2<f32>(Construct(Source{{12, 34}}, ty.Of(alias)), vec2<f32>());
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1896,12 +1833,10 @@
 
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns; i++) {
-    args.push_back(create<ast::TypeConstructorExpression>(
-        Source{{12, i}}, ty.Of(vec_alias), ExprList()));
+    args.push_back(Construct(Source{{12, i}}, ty.Of(vec_alias)));
   }
 
-  auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
-                                                    std::move(args));
+  auto* tc = Construct(Source{}, matrix_type, std::move(args));
   WrapInFunction(tc);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -1915,12 +1850,10 @@
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns; i++) {
     auto* vec_type = ty.vec(ty.Of(f32_alias), param.rows);
-    args.push_back(create<ast::TypeConstructorExpression>(
-        Source{{12, i}}, vec_type, ExprList()));
+    args.push_back(Construct(Source{{12, i}}, vec_type));
   }
 
-  auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
-                                                    std::move(args));
+  auto* tc = Construct(Source{}, matrix_type, std::move(args));
   WrapInFunction(tc);
 
   EXPECT_FALSE(r()->Resolve());
@@ -1937,13 +1870,11 @@
   ast::ExpressionList args;
   for (uint32_t i = 1; i <= param.columns; i++) {
     auto* vec_type = ty.vec(ty.Of(f32_alias), param.rows);
-    args.push_back(create<ast::TypeConstructorExpression>(
-        Source{{12, i}}, vec_type, ExprList()));
+    args.push_back(Construct(Source{{12, i}}, vec_type));
   }
 
   auto* matrix_type = ty.mat<f32>(param.columns, param.rows);
-  auto* tc = create<ast::TypeConstructorExpression>(Source{}, matrix_type,
-                                                    std::move(args));
+  auto* tc = Construct(Source{}, matrix_type, std::move(args));
   WrapInFunction(tc);
 
   EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -2010,8 +1941,7 @@
     }
   }
   auto* s = Structure("s", members);
-  auto* tc = create<ast::TypeConstructorExpression>(Source{{12, 34}}, ty.Of(s),
-                                                    values);
+  auto* tc = Construct(Source{{12, 34}}, ty.Of(s), values);
   WrapInFunction(tc);
   EXPECT_FALSE(r()->Resolve());
   EXPECT_EQ(r()->error(),
@@ -2035,8 +1965,7 @@
     values.push_back(ctor_value_expr);
   }
   auto* s = Structure("s", members);
-  auto* tc = create<ast::TypeConstructorExpression>(Source{{12, 34}}, ty.Of(s),
-                                                    values);
+  auto* tc = Construct(Source{{12, 34}}, ty.Of(s), values);
   WrapInFunction(tc);
   EXPECT_FALSE(r()->Resolve());
   EXPECT_EQ(r()->error(),
@@ -2075,7 +2004,7 @@
     values.push_back(ctor_value_expr);
   }
   auto* s = Structure("s", members);
-  auto* tc = create<ast::TypeConstructorExpression>(ty.Of(s), values);
+  auto* tc = Construct(ty.Of(s), values);
   WrapInFunction(tc);
 
   std::string found = FriendlyName(ctor_params.ast(*this));
@@ -2102,8 +2031,7 @@
   auto* m2 = Member("m2", ty.i32());
   auto* s = Structure("s", {m0, m1, m2});
 
-  auto* tc = create<ast::TypeConstructorExpression>(Source{{12, 34}}, ty.Of(s),
-                                                    ExprList(1, 1, 1));
+  auto* tc = Construct(Source{{12, 34}}, ty.Of(s), 1, 1, 1);
   WrapInFunction(tc);
   EXPECT_FALSE(r()->Resolve());
   EXPECT_EQ(r()->error(),
@@ -2114,8 +2042,7 @@
 TEST_F(ResolverTypeConstructorValidationTest, Expr_Constructor_Struct) {
   auto* m = Member("m", ty.i32());
   auto* s = Structure("MyInputs", {m});
-  auto* tc = create<ast::TypeConstructorExpression>(Source{{12, 34}}, ty.Of(s),
-                                                    ExprList());
+  auto* tc = Construct(Source{{12, 34}}, ty.Of(s));
   WrapInFunction(tc);
   EXPECT_TRUE(r()->Resolve()) << r()->error();
 }
diff --git a/src/resolver/validation_test.cc b/src/resolver/validation_test.cc
index 3d27e03..09a42d8 100644
--- a/src/resolver/validation_test.cc
+++ b/src/resolver/validation_test.cc
@@ -1035,9 +1035,9 @@
 
 TEST_F(ResolverTest, Expr_Constructor_Cast_Pointer) {
   auto* vf = Var("vf", ty.f32());
-  auto* c = create<ast::TypeConstructorExpression>(
-      Source{{12, 34}}, ty.pointer<i32>(ast::StorageClass::kFunction),
-      ExprList(vf));
+  auto* c =
+      Construct(Source{{12, 34}}, ty.pointer<i32>(ast::StorageClass::kFunction),
+                ExprList(vf));
   auto* ip = Const("ip", ty.pointer<i32>(ast::StorageClass::kFunction), c);
   WrapInFunction(Decl(vf), Decl(ip));
 
diff --git a/src/transform/decompose_memory_access.cc b/src/transform/decompose_memory_access.cc
index a06f8e0..bd40a6f 100644
--- a/src/transform/decompose_memory_access.cc
+++ b/src/transform/decompose_memory_access.cc
@@ -522,11 +522,11 @@
                 values.emplace_back(b.Call(load, "buffer", offset));
               }
             }
-            b.Func(name, params, CreateASTTypeFor(ctx, el_ty),
-                   {
-                       b.Return(b.create<ast::TypeConstructorExpression>(
-                           CreateASTTypeFor(ctx, el_ty), values)),
-                   });
+            b.Func(
+                name, params, CreateASTTypeFor(ctx, el_ty),
+                {
+                    b.Return(b.Construct(CreateASTTypeFor(ctx, el_ty), values)),
+                });
           }
           return name;
         });
diff --git a/src/transform/vertex_pulling.cc b/src/transform/vertex_pulling.cc
index 1fc01fb..bafe5ca 100644
--- a/src/transform/vertex_pulling.cc
+++ b/src/transform/vertex_pulling.cc
@@ -715,7 +715,7 @@
           LoadPrimitive(array_base, primitive_offset, buffer, base_format));
     }
 
-    return ctx.dst->create<ast::TypeConstructorExpression>(
+    return ctx.dst->Construct(
         ctx.dst->create<ast::Vector>(base_type, count), std::move(expr_list));
   }