writer/hlsl tests: Replace std::make_unique<T> -> create<T>

create() is currently just a simple forwarder to std::make_unique<>, but
will be later replaced with a function that returns a raw pointer,
and owned by the context.

Bug: tint:322
Change-Id: I06511413e4d1afd84504f9ec8ab36f2c02764b9b
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/32671
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/writer/hlsl/generator_impl_alias_type_test.cc b/src/writer/hlsl/generator_impl_alias_type_test.cc
index ae8a6e6..2d80431 100644
--- a/src/writer/hlsl/generator_impl_alias_type_test.cc
+++ b/src/writer/hlsl/generator_impl_alias_type_test.cc
@@ -51,16 +51,14 @@
   ast::type::F32Type f32;
 
   ast::StructMemberList members;
-  members.push_back(std::make_unique<ast::StructMember>(
-      "a", &f32, ast::StructMemberDecorationList{}));
+  members.push_back(
+      create<ast::StructMember>("a", &f32, ast::StructMemberDecorationList{}));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(4, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &i32, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(4, Source{}));
+  members.push_back(create<ast::StructMember>("b", &i32, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("A", std::move(str));
diff --git a/src/writer/hlsl/generator_impl_array_accessor_test.cc b/src/writer/hlsl/generator_impl_array_accessor_test.cc
index b399f7e..5842e7d 100644
--- a/src/writer/hlsl/generator_impl_array_accessor_test.cc
+++ b/src/writer/hlsl/generator_impl_array_accessor_test.cc
@@ -31,9 +31,9 @@
 
 TEST_F(HlslGeneratorImplTest_Expression, EmitExpression_ArrayAccessor) {
   ast::type::I32Type i32;
-  auto lit = std::make_unique<ast::SintLiteral>(&i32, 5);
-  auto idx = std::make_unique<ast::ScalarConstructorExpression>(std::move(lit));
-  auto ary = std::make_unique<ast::IdentifierExpression>("ary");
+  auto lit = create<ast::SintLiteral>(&i32, 5);
+  auto idx = create<ast::ScalarConstructorExpression>(std::move(lit));
+  auto ary = create<ast::IdentifierExpression>("ary");
 
   ast::ArrayAccessorExpression expr(std::move(ary), std::move(idx));
 
@@ -42,8 +42,8 @@
 }
 
 TEST_F(HlslGeneratorImplTest_Expression, EmitArrayAccessor) {
-  auto ary = std::make_unique<ast::IdentifierExpression>("ary");
-  auto idx = std::make_unique<ast::IdentifierExpression>("idx");
+  auto ary = create<ast::IdentifierExpression>("ary");
+  auto idx = create<ast::IdentifierExpression>("idx");
 
   ast::ArrayAccessorExpression expr(std::move(ary), std::move(idx));
 
diff --git a/src/writer/hlsl/generator_impl_assign_test.cc b/src/writer/hlsl/generator_impl_assign_test.cc
index 8b9da6a..37103d4 100644
--- a/src/writer/hlsl/generator_impl_assign_test.cc
+++ b/src/writer/hlsl/generator_impl_assign_test.cc
@@ -28,8 +28,8 @@
 using HlslGeneratorImplTest_Assign = TestHelper;
 
 TEST_F(HlslGeneratorImplTest_Assign, Emit_Assign) {
-  auto lhs = std::make_unique<ast::IdentifierExpression>("lhs");
-  auto rhs = std::make_unique<ast::IdentifierExpression>("rhs");
+  auto lhs = create<ast::IdentifierExpression>("lhs");
+  auto rhs = create<ast::IdentifierExpression>("rhs");
   ast::AssignmentStatement assign(std::move(lhs), std::move(rhs));
 
   gen.increment_indent();
diff --git a/src/writer/hlsl/generator_impl_binary_test.cc b/src/writer/hlsl/generator_impl_binary_test.cc
index fe5b0ad..c201f47 100644
--- a/src/writer/hlsl/generator_impl_binary_test.cc
+++ b/src/writer/hlsl/generator_impl_binary_test.cc
@@ -54,8 +54,8 @@
 TEST_P(HlslBinaryTest, Emit) {
   auto params = GetParam();
 
-  auto left = std::make_unique<ast::IdentifierExpression>("left");
-  auto right = std::make_unique<ast::IdentifierExpression>("right");
+  auto left = create<ast::IdentifierExpression>("left");
+  auto right = create<ast::IdentifierExpression>("right");
 
   ast::BinaryExpression expr(params.op, std::move(left), std::move(right));
 
@@ -84,8 +84,8 @@
         BinaryData{"(left % right)", ast::BinaryOp::kModulo}));
 
 TEST_F(HlslGeneratorImplTest_Binary, Logical_And) {
-  auto left = std::make_unique<ast::IdentifierExpression>("left");
-  auto right = std::make_unique<ast::IdentifierExpression>("right");
+  auto left = create<ast::IdentifierExpression>("left");
+  auto right = create<ast::IdentifierExpression>("right");
 
   ast::BinaryExpression expr(ast::BinaryOp::kLogicalAnd, std::move(left),
                              std::move(right));
@@ -101,17 +101,17 @@
 
 TEST_F(HlslGeneratorImplTest_Binary, Logical_Multi) {
   // (a && b) || (c || d)
-  auto a = std::make_unique<ast::IdentifierExpression>("a");
-  auto b = std::make_unique<ast::IdentifierExpression>("b");
-  auto c = std::make_unique<ast::IdentifierExpression>("c");
-  auto d = std::make_unique<ast::IdentifierExpression>("d");
+  auto a = create<ast::IdentifierExpression>("a");
+  auto b = create<ast::IdentifierExpression>("b");
+  auto c = create<ast::IdentifierExpression>("c");
+  auto d = create<ast::IdentifierExpression>("d");
 
   ast::BinaryExpression expr(
       ast::BinaryOp::kLogicalOr,
-      std::make_unique<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd,
-                                              std::move(a), std::move(b)),
-      std::make_unique<ast::BinaryExpression>(ast::BinaryOp::kLogicalOr,
-                                              std::move(c), std::move(d)));
+      create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd, std::move(a),
+                                    std::move(b)),
+      create<ast::BinaryExpression>(ast::BinaryOp::kLogicalOr, std::move(c),
+                                    std::move(d)));
 
   ASSERT_TRUE(gen.EmitExpression(pre, out, &expr)) << gen.error();
   EXPECT_EQ(result(), "(_tint_tmp_0)");
@@ -131,8 +131,8 @@
 }
 
 TEST_F(HlslGeneratorImplTest_Binary, Logical_Or) {
-  auto left = std::make_unique<ast::IdentifierExpression>("left");
-  auto right = std::make_unique<ast::IdentifierExpression>("right");
+  auto left = create<ast::IdentifierExpression>("left");
+  auto right = create<ast::IdentifierExpression>("right");
 
   ast::BinaryExpression expr(ast::BinaryOp::kLogicalOr, std::move(left),
                              std::move(right));
@@ -157,37 +157,36 @@
 
   ast::type::I32Type i32;
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::ReturnStatement>(
-      std::make_unique<ast::ScalarConstructorExpression>(
-          std::make_unique<ast::SintLiteral>(&i32, 3))));
-  auto else_stmt = std::make_unique<ast::ElseStatement>(std::move(body));
+  auto body = create<ast::BlockStatement>();
+  body->append(
+      create<ast::ReturnStatement>(create<ast::ScalarConstructorExpression>(
+          create<ast::SintLiteral>(&i32, 3))));
+  auto else_stmt = create<ast::ElseStatement>(std::move(body));
 
-  body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::ReturnStatement>(
-      std::make_unique<ast::ScalarConstructorExpression>(
-          std::make_unique<ast::SintLiteral>(&i32, 2))));
-  auto else_if_stmt = std::make_unique<ast::ElseStatement>(
-      std::make_unique<ast::BinaryExpression>(
-          ast::BinaryOp::kLogicalOr,
-          std::make_unique<ast::IdentifierExpression>("b"),
-          std::make_unique<ast::IdentifierExpression>("c")),
+  body = create<ast::BlockStatement>();
+  body->append(
+      create<ast::ReturnStatement>(create<ast::ScalarConstructorExpression>(
+          create<ast::SintLiteral>(&i32, 2))));
+  auto else_if_stmt = create<ast::ElseStatement>(
+      create<ast::BinaryExpression>(ast::BinaryOp::kLogicalOr,
+                                    create<ast::IdentifierExpression>("b"),
+                                    create<ast::IdentifierExpression>("c")),
       std::move(body));
 
   ast::ElseStatementList else_stmts;
   else_stmts.push_back(std::move(else_if_stmt));
   else_stmts.push_back(std::move(else_stmt));
 
-  body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::ReturnStatement>(
-      std::make_unique<ast::ScalarConstructorExpression>(
-          std::make_unique<ast::SintLiteral>(&i32, 1))));
+  body = create<ast::BlockStatement>();
+  body->append(
+      create<ast::ReturnStatement>(create<ast::ScalarConstructorExpression>(
+          create<ast::SintLiteral>(&i32, 1))));
 
-  ast::IfStatement expr(std::make_unique<ast::BinaryExpression>(
-                            ast::BinaryOp::kLogicalAnd,
-                            std::make_unique<ast::IdentifierExpression>("a"),
-                            std::make_unique<ast::IdentifierExpression>("b")),
-                        std::move(body));
+  ast::IfStatement expr(
+      create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd,
+                                    create<ast::IdentifierExpression>("a"),
+                                    create<ast::IdentifierExpression>("b")),
+      std::move(body));
   expr.set_else_statements(std::move(else_stmts));
 
   ASSERT_TRUE(gen.EmitStatement(out, &expr)) << gen.error();
@@ -213,14 +212,14 @@
 
 TEST_F(HlslGeneratorImplTest_Binary, Return_WithLogical) {
   // return (a && b) || c;
-  auto a = std::make_unique<ast::IdentifierExpression>("a");
-  auto b = std::make_unique<ast::IdentifierExpression>("b");
-  auto c = std::make_unique<ast::IdentifierExpression>("c");
+  auto a = create<ast::IdentifierExpression>("a");
+  auto b = create<ast::IdentifierExpression>("b");
+  auto c = create<ast::IdentifierExpression>("c");
 
-  ast::ReturnStatement expr(std::make_unique<ast::BinaryExpression>(
+  ast::ReturnStatement expr(create<ast::BinaryExpression>(
       ast::BinaryOp::kLogicalOr,
-      std::make_unique<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd,
-                                              std::move(a), std::move(b)),
+      create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd, std::move(a),
+                                    std::move(b)),
       std::move(c)));
 
   ASSERT_TRUE(gen.EmitStatement(out, &expr)) << gen.error();
@@ -238,17 +237,17 @@
 
 TEST_F(HlslGeneratorImplTest_Binary, Assign_WithLogical) {
   // a = (b || c) && d;
-  auto a = std::make_unique<ast::IdentifierExpression>("a");
-  auto b = std::make_unique<ast::IdentifierExpression>("b");
-  auto c = std::make_unique<ast::IdentifierExpression>("c");
-  auto d = std::make_unique<ast::IdentifierExpression>("d");
+  auto a = create<ast::IdentifierExpression>("a");
+  auto b = create<ast::IdentifierExpression>("b");
+  auto c = create<ast::IdentifierExpression>("c");
+  auto d = create<ast::IdentifierExpression>("d");
 
   ast::AssignmentStatement expr(
       std::move(a),
-      std::make_unique<ast::BinaryExpression>(
+      create<ast::BinaryExpression>(
           ast::BinaryOp::kLogicalAnd,
-          std::make_unique<ast::BinaryExpression>(ast::BinaryOp::kLogicalOr,
-                                                  std::move(b), std::move(c)),
+          create<ast::BinaryExpression>(ast::BinaryOp::kLogicalOr, std::move(b),
+                                        std::move(c)),
           std::move(d)));
 
   ASSERT_TRUE(gen.EmitStatement(out, &expr)) << gen.error();
@@ -268,16 +267,16 @@
   // var a : bool = (b && c) || d;
   ast::type::BoolType bool_type;
 
-  auto b = std::make_unique<ast::IdentifierExpression>("b");
-  auto c = std::make_unique<ast::IdentifierExpression>("c");
-  auto d = std::make_unique<ast::IdentifierExpression>("d");
+  auto b = create<ast::IdentifierExpression>("b");
+  auto c = create<ast::IdentifierExpression>("c");
+  auto d = create<ast::IdentifierExpression>("d");
 
-  auto var = std::make_unique<ast::Variable>("a", ast::StorageClass::kFunction,
-                                             &bool_type);
-  var->set_constructor(std::make_unique<ast::BinaryExpression>(
+  auto var =
+      create<ast::Variable>("a", ast::StorageClass::kFunction, &bool_type);
+  var->set_constructor(create<ast::BinaryExpression>(
       ast::BinaryOp::kLogicalOr,
-      std::make_unique<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd,
-                                              std::move(b), std::move(c)),
+      create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd, std::move(b),
+                                    std::move(c)),
       std::move(d)));
 
   ast::VariableDeclStatement expr(std::move(var));
@@ -299,15 +298,15 @@
   // as<i32>(a && (b || c))
   ast::type::I32Type i32;
 
-  auto a = std::make_unique<ast::IdentifierExpression>("a");
-  auto b = std::make_unique<ast::IdentifierExpression>("b");
-  auto c = std::make_unique<ast::IdentifierExpression>("c");
+  auto a = create<ast::IdentifierExpression>("a");
+  auto b = create<ast::IdentifierExpression>("b");
+  auto c = create<ast::IdentifierExpression>("c");
 
   ast::BitcastExpression expr(
-      &i32, std::make_unique<ast::BinaryExpression>(
+      &i32, create<ast::BinaryExpression>(
                 ast::BinaryOp::kLogicalAnd, std::move(a),
-                std::make_unique<ast::BinaryExpression>(
-                    ast::BinaryOp::kLogicalOr, std::move(b), std::move(c))));
+                create<ast::BinaryExpression>(ast::BinaryOp::kLogicalOr,
+                                              std::move(b), std::move(c))));
 
   ASSERT_TRUE(gen.EmitExpression(pre, out, &expr)) << gen.error();
   EXPECT_EQ(pre_result(), R"(bool _tint_tmp = a;
@@ -327,32 +326,27 @@
 
   ast::type::VoidType void_type;
 
-  auto func =
-      std::make_unique<ast::Function>("foo", ast::VariableList{}, &void_type);
+  auto func = create<ast::Function>("foo", ast::VariableList{}, &void_type);
   mod.AddFunction(std::move(func));
 
   ast::ExpressionList params;
-  params.push_back(std::make_unique<ast::BinaryExpression>(
+  params.push_back(create<ast::BinaryExpression>(
+      ast::BinaryOp::kLogicalAnd, create<ast::IdentifierExpression>("a"),
+      create<ast::IdentifierExpression>("b")));
+  params.push_back(create<ast::BinaryExpression>(
+      ast::BinaryOp::kLogicalOr, create<ast::IdentifierExpression>("c"),
+      create<ast::IdentifierExpression>("d")));
+  params.push_back(create<ast::BinaryExpression>(
       ast::BinaryOp::kLogicalAnd,
-      std::make_unique<ast::IdentifierExpression>("a"),
-      std::make_unique<ast::IdentifierExpression>("b")));
-  params.push_back(std::make_unique<ast::BinaryExpression>(
-      ast::BinaryOp::kLogicalOr,
-      std::make_unique<ast::IdentifierExpression>("c"),
-      std::make_unique<ast::IdentifierExpression>("d")));
-  params.push_back(std::make_unique<ast::BinaryExpression>(
-      ast::BinaryOp::kLogicalAnd,
-      std::make_unique<ast::BinaryExpression>(
-          ast::BinaryOp::kLogicalOr,
-          std::make_unique<ast::IdentifierExpression>("a"),
-          std::make_unique<ast::IdentifierExpression>("c")),
-      std::make_unique<ast::BinaryExpression>(
-          ast::BinaryOp::kLogicalOr,
-          std::make_unique<ast::IdentifierExpression>("b"),
-          std::make_unique<ast::IdentifierExpression>("d"))));
+      create<ast::BinaryExpression>(ast::BinaryOp::kLogicalOr,
+                                    create<ast::IdentifierExpression>("a"),
+                                    create<ast::IdentifierExpression>("c")),
+      create<ast::BinaryExpression>(ast::BinaryOp::kLogicalOr,
+                                    create<ast::IdentifierExpression>("b"),
+                                    create<ast::IdentifierExpression>("d"))));
 
-  ast::CallStatement expr(std::make_unique<ast::CallExpression>(
-      std::make_unique<ast::IdentifierExpression>("foo"), std::move(params)));
+  ast::CallStatement expr(create<ast::CallExpression>(
+      create<ast::IdentifierExpression>("foo"), std::move(params)));
 
   ASSERT_TRUE(gen.EmitStatement(out, &expr)) << gen.error();
   EXPECT_EQ(result(), R"(bool _tint_tmp = a;
diff --git a/src/writer/hlsl/generator_impl_bitcast_test.cc b/src/writer/hlsl/generator_impl_bitcast_test.cc
index e7cd737..cfa6aec 100644
--- a/src/writer/hlsl/generator_impl_bitcast_test.cc
+++ b/src/writer/hlsl/generator_impl_bitcast_test.cc
@@ -31,7 +31,7 @@
 
 TEST_F(HlslGeneratorImplTest_Bitcast, EmitExpression_Bitcast_Float) {
   ast::type::F32Type f32;
-  auto id = std::make_unique<ast::IdentifierExpression>("id");
+  auto id = create<ast::IdentifierExpression>("id");
   ast::BitcastExpression bitcast(&f32, std::move(id));
 
   ASSERT_TRUE(gen.EmitExpression(pre, out, &bitcast)) << gen.error();
@@ -40,7 +40,7 @@
 
 TEST_F(HlslGeneratorImplTest_Bitcast, EmitExpression_Bitcast_Int) {
   ast::type::I32Type i32;
-  auto id = std::make_unique<ast::IdentifierExpression>("id");
+  auto id = create<ast::IdentifierExpression>("id");
   ast::BitcastExpression bitcast(&i32, std::move(id));
 
   ASSERT_TRUE(gen.EmitExpression(pre, out, &bitcast)) << gen.error();
@@ -49,7 +49,7 @@
 
 TEST_F(HlslGeneratorImplTest_Bitcast, EmitExpression_Bitcast_Uint) {
   ast::type::U32Type u32;
-  auto id = std::make_unique<ast::IdentifierExpression>("id");
+  auto id = create<ast::IdentifierExpression>("id");
   ast::BitcastExpression bitcast(&u32, std::move(id));
 
   ASSERT_TRUE(gen.EmitExpression(pre, out, &bitcast)) << gen.error();
diff --git a/src/writer/hlsl/generator_impl_block_test.cc b/src/writer/hlsl/generator_impl_block_test.cc
index 6d3549a..7f0194e 100644
--- a/src/writer/hlsl/generator_impl_block_test.cc
+++ b/src/writer/hlsl/generator_impl_block_test.cc
@@ -27,7 +27,7 @@
 
 TEST_F(HlslGeneratorImplTest_Block, Emit_Block) {
   ast::BlockStatement b;
-  b.append(std::make_unique<ast::DiscardStatement>());
+  b.append(create<ast::DiscardStatement>());
 
   gen.increment_indent();
 
@@ -40,7 +40,7 @@
 
 TEST_F(HlslGeneratorImplTest_Block, Emit_Block_WithoutNewline) {
   ast::BlockStatement b;
-  b.append(std::make_unique<ast::DiscardStatement>());
+  b.append(create<ast::DiscardStatement>());
 
   gen.increment_indent();
 
diff --git a/src/writer/hlsl/generator_impl_call_test.cc b/src/writer/hlsl/generator_impl_call_test.cc
index 58a8a1e..6a50881 100644
--- a/src/writer/hlsl/generator_impl_call_test.cc
+++ b/src/writer/hlsl/generator_impl_call_test.cc
@@ -32,11 +32,10 @@
 TEST_F(HlslGeneratorImplTest_Call, EmitExpression_Call_WithoutParams) {
   ast::type::VoidType void_type;
 
-  auto id = std::make_unique<ast::IdentifierExpression>("my_func");
+  auto id = create<ast::IdentifierExpression>("my_func");
   ast::CallExpression call(std::move(id), {});
 
-  auto func = std::make_unique<ast::Function>("my_func", ast::VariableList{},
-                                              &void_type);
+  auto func = create<ast::Function>("my_func", ast::VariableList{}, &void_type);
   mod.AddFunction(std::move(func));
 
   ASSERT_TRUE(gen.EmitExpression(pre, out, &call)) << gen.error();
@@ -46,14 +45,13 @@
 TEST_F(HlslGeneratorImplTest_Call, EmitExpression_Call_WithParams) {
   ast::type::VoidType void_type;
 
-  auto id = std::make_unique<ast::IdentifierExpression>("my_func");
+  auto id = create<ast::IdentifierExpression>("my_func");
   ast::ExpressionList params;
-  params.push_back(std::make_unique<ast::IdentifierExpression>("param1"));
-  params.push_back(std::make_unique<ast::IdentifierExpression>("param2"));
+  params.push_back(create<ast::IdentifierExpression>("param1"));
+  params.push_back(create<ast::IdentifierExpression>("param2"));
   ast::CallExpression call(std::move(id), std::move(params));
 
-  auto func = std::make_unique<ast::Function>("my_func", ast::VariableList{},
-                                              &void_type);
+  auto func = create<ast::Function>("my_func", ast::VariableList{}, &void_type);
   mod.AddFunction(std::move(func));
 
   ASSERT_TRUE(gen.EmitExpression(pre, out, &call)) << gen.error();
@@ -63,15 +61,14 @@
 TEST_F(HlslGeneratorImplTest_Call, EmitStatement_Call) {
   ast::type::VoidType void_type;
 
-  auto id = std::make_unique<ast::IdentifierExpression>("my_func");
+  auto id = create<ast::IdentifierExpression>("my_func");
   ast::ExpressionList params;
-  params.push_back(std::make_unique<ast::IdentifierExpression>("param1"));
-  params.push_back(std::make_unique<ast::IdentifierExpression>("param2"));
+  params.push_back(create<ast::IdentifierExpression>("param1"));
+  params.push_back(create<ast::IdentifierExpression>("param2"));
   ast::CallStatement call(
-      std::make_unique<ast::CallExpression>(std::move(id), std::move(params)));
+      create<ast::CallExpression>(std::move(id), std::move(params)));
 
-  auto func = std::make_unique<ast::Function>("my_func", ast::VariableList{},
-                                              &void_type);
+  auto func = create<ast::Function>("my_func", ast::VariableList{}, &void_type);
   mod.AddFunction(std::move(func));
   gen.increment_indent();
   ASSERT_TRUE(gen.EmitStatement(out, &call)) << gen.error();
diff --git a/src/writer/hlsl/generator_impl_case_test.cc b/src/writer/hlsl/generator_impl_case_test.cc
index 686e16e..8da7d20 100644
--- a/src/writer/hlsl/generator_impl_case_test.cc
+++ b/src/writer/hlsl/generator_impl_case_test.cc
@@ -33,11 +33,11 @@
 TEST_F(HlslGeneratorImplTest_Case, Emit_Case) {
   ast::type::I32Type i32;
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::BreakStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::BreakStatement>());
 
   ast::CaseSelectorList lit;
-  lit.push_back(std::make_unique<ast::SintLiteral>(&i32, 5));
+  lit.push_back(create<ast::SintLiteral>(&i32, 5));
   ast::CaseStatement c(std::move(lit), std::move(body));
 
   gen.increment_indent();
@@ -53,8 +53,8 @@
   ast::type::I32Type i32;
 
   ast::CaseSelectorList lit;
-  lit.push_back(std::make_unique<ast::SintLiteral>(&i32, 5));
-  ast::CaseStatement c(std::move(lit), std::make_unique<ast::BlockStatement>());
+  lit.push_back(create<ast::SintLiteral>(&i32, 5));
+  ast::CaseStatement c(std::move(lit), create<ast::BlockStatement>());
 
   gen.increment_indent();
 
@@ -68,11 +68,11 @@
 TEST_F(HlslGeneratorImplTest_Case, Emit_Case_WithFallthrough) {
   ast::type::I32Type i32;
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::FallthroughStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::FallthroughStatement>());
 
   ast::CaseSelectorList lit;
-  lit.push_back(std::make_unique<ast::SintLiteral>(&i32, 5));
+  lit.push_back(create<ast::SintLiteral>(&i32, 5));
   ast::CaseStatement c(std::move(lit), std::move(body));
 
   gen.increment_indent();
@@ -87,12 +87,12 @@
 TEST_F(HlslGeneratorImplTest_Case, Emit_Case_MultipleSelectors) {
   ast::type::I32Type i32;
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::BreakStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::BreakStatement>());
 
   ast::CaseSelectorList lit;
-  lit.push_back(std::make_unique<ast::SintLiteral>(&i32, 5));
-  lit.push_back(std::make_unique<ast::SintLiteral>(&i32, 6));
+  lit.push_back(create<ast::SintLiteral>(&i32, 5));
+  lit.push_back(create<ast::SintLiteral>(&i32, 6));
   ast::CaseStatement c(std::move(lit), std::move(body));
 
   gen.increment_indent();
@@ -108,8 +108,8 @@
 TEST_F(HlslGeneratorImplTest_Case, Emit_Case_Default) {
   ast::CaseStatement c;
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::BreakStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::BreakStatement>());
   c.set_body(std::move(body));
 
   gen.increment_indent();
diff --git a/src/writer/hlsl/generator_impl_cast_test.cc b/src/writer/hlsl/generator_impl_cast_test.cc
index 9c88e51..6052494 100644
--- a/src/writer/hlsl/generator_impl_cast_test.cc
+++ b/src/writer/hlsl/generator_impl_cast_test.cc
@@ -32,7 +32,7 @@
   ast::type::F32Type f32;
 
   ast::ExpressionList params;
-  params.push_back(std::make_unique<ast::IdentifierExpression>("id"));
+  params.push_back(create<ast::IdentifierExpression>("id"));
 
   ast::TypeConstructorExpression cast(&f32, std::move(params));
 
@@ -45,7 +45,7 @@
   ast::type::VectorType vec3(&f32, 3);
 
   ast::ExpressionList params;
-  params.push_back(std::make_unique<ast::IdentifierExpression>("id"));
+  params.push_back(create<ast::IdentifierExpression>("id"));
 
   ast::TypeConstructorExpression cast(&vec3, std::move(params));
 
diff --git a/src/writer/hlsl/generator_impl_constructor_test.cc b/src/writer/hlsl/generator_impl_constructor_test.cc
index 1a953d0..96ccff7 100644
--- a/src/writer/hlsl/generator_impl_constructor_test.cc
+++ b/src/writer/hlsl/generator_impl_constructor_test.cc
@@ -37,7 +37,7 @@
 
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Bool) {
   ast::type::BoolType bool_type;
-  auto lit = std::make_unique<ast::BoolLiteral>(&bool_type, false);
+  auto lit = create<ast::BoolLiteral>(&bool_type, false);
   ast::ScalarConstructorExpression expr(std::move(lit));
 
   ASSERT_TRUE(gen.EmitConstructor(pre, out, &expr)) << gen.error();
@@ -46,7 +46,7 @@
 
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Int) {
   ast::type::I32Type i32;
-  auto lit = std::make_unique<ast::SintLiteral>(&i32, -12345);
+  auto lit = create<ast::SintLiteral>(&i32, -12345);
   ast::ScalarConstructorExpression expr(std::move(lit));
 
   ASSERT_TRUE(gen.EmitConstructor(pre, out, &expr)) << gen.error();
@@ -55,7 +55,7 @@
 
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_UInt) {
   ast::type::U32Type u32;
-  auto lit = std::make_unique<ast::UintLiteral>(&u32, 56779);
+  auto lit = create<ast::UintLiteral>(&u32, 56779);
   ast::ScalarConstructorExpression expr(std::move(lit));
 
   ASSERT_TRUE(gen.EmitConstructor(pre, out, &expr)) << gen.error();
@@ -65,8 +65,7 @@
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Float) {
   ast::type::F32Type f32;
   // Use a number close to 1<<30 but whose decimal representation ends in 0.
-  auto lit = std::make_unique<ast::FloatLiteral>(
-      &f32, static_cast<float>((1 << 30) - 4));
+  auto lit = create<ast::FloatLiteral>(&f32, static_cast<float>((1 << 30) - 4));
   ast::ScalarConstructorExpression expr(std::move(lit));
 
   ASSERT_TRUE(gen.EmitConstructor(pre, out, &expr)) << gen.error();
@@ -76,10 +75,9 @@
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Float) {
   ast::type::F32Type f32;
 
-  auto lit = std::make_unique<ast::FloatLiteral>(&f32, -1.2e-5);
+  auto lit = create<ast::FloatLiteral>(&f32, -1.2e-5);
   ast::ExpressionList values;
-  values.push_back(
-      std::make_unique<ast::ScalarConstructorExpression>(std::move(lit)));
+  values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit)));
 
   ast::TypeConstructorExpression expr(&f32, std::move(values));
 
@@ -90,10 +88,9 @@
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Bool) {
   ast::type::BoolType b;
 
-  auto lit = std::make_unique<ast::BoolLiteral>(&b, true);
+  auto lit = create<ast::BoolLiteral>(&b, true);
   ast::ExpressionList values;
-  values.push_back(
-      std::make_unique<ast::ScalarConstructorExpression>(std::move(lit)));
+  values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit)));
 
   ast::TypeConstructorExpression expr(&b, std::move(values));
 
@@ -104,10 +101,9 @@
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Int) {
   ast::type::I32Type i32;
 
-  auto lit = std::make_unique<ast::SintLiteral>(&i32, -12345);
+  auto lit = create<ast::SintLiteral>(&i32, -12345);
   ast::ExpressionList values;
-  values.push_back(
-      std::make_unique<ast::ScalarConstructorExpression>(std::move(lit)));
+  values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit)));
 
   ast::TypeConstructorExpression expr(&i32, std::move(values));
 
@@ -118,10 +114,9 @@
 TEST_F(HlslGeneratorImplTest_Constructor, EmitConstructor_Type_Uint) {
   ast::type::U32Type u32;
 
-  auto lit = std::make_unique<ast::UintLiteral>(&u32, 12345);
+  auto lit = create<ast::UintLiteral>(&u32, 12345);
   ast::ExpressionList values;
-  values.push_back(
-      std::make_unique<ast::ScalarConstructorExpression>(std::move(lit)));
+  values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit)));
 
   ast::TypeConstructorExpression expr(&u32, std::move(values));
 
@@ -133,16 +128,13 @@
   ast::type::F32Type f32;
   ast::type::VectorType vec(&f32, 3);
 
-  auto lit1 = std::make_unique<ast::FloatLiteral>(&f32, 1.f);
-  auto lit2 = std::make_unique<ast::FloatLiteral>(&f32, 2.f);
-  auto lit3 = std::make_unique<ast::FloatLiteral>(&f32, 3.f);
+  auto lit1 = create<ast::FloatLiteral>(&f32, 1.f);
+  auto lit2 = create<ast::FloatLiteral>(&f32, 2.f);
+  auto lit3 = create<ast::FloatLiteral>(&f32, 3.f);
   ast::ExpressionList values;
-  values.push_back(
-      std::make_unique<ast::ScalarConstructorExpression>(std::move(lit1)));
-  values.push_back(
-      std::make_unique<ast::ScalarConstructorExpression>(std::move(lit2)));
-  values.push_back(
-      std::make_unique<ast::ScalarConstructorExpression>(std::move(lit3)));
+  values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit1)));
+  values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit2)));
+  values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit3)));
 
   ast::TypeConstructorExpression expr(&vec, std::move(values));
 
@@ -173,23 +165,20 @@
   ast::ExpressionList mat_values;
 
   for (size_t i = 0; i < 2; i++) {
-    auto lit1 = std::make_unique<ast::FloatLiteral>(
-        &f32, static_cast<float>(1 + (i * 2)));
-    auto lit2 = std::make_unique<ast::FloatLiteral>(
-        &f32, static_cast<float>(2 + (i * 2)));
-    auto lit3 = std::make_unique<ast::FloatLiteral>(
-        &f32, static_cast<float>(3 + (i * 2)));
+    auto lit1 =
+        create<ast::FloatLiteral>(&f32, static_cast<float>(1 + (i * 2)));
+    auto lit2 =
+        create<ast::FloatLiteral>(&f32, static_cast<float>(2 + (i * 2)));
+    auto lit3 =
+        create<ast::FloatLiteral>(&f32, static_cast<float>(3 + (i * 2)));
 
     ast::ExpressionList values;
-    values.push_back(
-        std::make_unique<ast::ScalarConstructorExpression>(std::move(lit1)));
-    values.push_back(
-        std::make_unique<ast::ScalarConstructorExpression>(std::move(lit2)));
-    values.push_back(
-        std::make_unique<ast::ScalarConstructorExpression>(std::move(lit3)));
+    values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit1)));
+    values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit2)));
+    values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit3)));
 
-    mat_values.push_back(std::make_unique<ast::TypeConstructorExpression>(
-        &vec, std::move(values)));
+    mat_values.push_back(
+        create<ast::TypeConstructorExpression>(&vec, std::move(values)));
   }
 
   ast::TypeConstructorExpression expr(&mat, std::move(mat_values));
@@ -212,23 +201,20 @@
   ast::ExpressionList ary_values;
 
   for (size_t i = 0; i < 3; i++) {
-    auto lit1 = std::make_unique<ast::FloatLiteral>(
-        &f32, static_cast<float>(1 + (i * 3)));
-    auto lit2 = std::make_unique<ast::FloatLiteral>(
-        &f32, static_cast<float>(2 + (i * 3)));
-    auto lit3 = std::make_unique<ast::FloatLiteral>(
-        &f32, static_cast<float>(3 + (i * 3)));
+    auto lit1 =
+        create<ast::FloatLiteral>(&f32, static_cast<float>(1 + (i * 3)));
+    auto lit2 =
+        create<ast::FloatLiteral>(&f32, static_cast<float>(2 + (i * 3)));
+    auto lit3 =
+        create<ast::FloatLiteral>(&f32, static_cast<float>(3 + (i * 3)));
 
     ast::ExpressionList values;
-    values.push_back(
-        std::make_unique<ast::ScalarConstructorExpression>(std::move(lit1)));
-    values.push_back(
-        std::make_unique<ast::ScalarConstructorExpression>(std::move(lit2)));
-    values.push_back(
-        std::make_unique<ast::ScalarConstructorExpression>(std::move(lit3)));
+    values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit1)));
+    values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit2)));
+    values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit3)));
 
-    ary_values.push_back(std::make_unique<ast::TypeConstructorExpression>(
-        &vec, std::move(values)));
+    ary_values.push_back(
+        create<ast::TypeConstructorExpression>(&vec, std::move(values)));
   }
 
   ast::TypeConstructorExpression expr(&ary, std::move(ary_values));
diff --git a/src/writer/hlsl/generator_impl_function_entry_point_data_test.cc b/src/writer/hlsl/generator_impl_function_entry_point_data_test.cc
index 9347e95..1803fd0 100644
--- a/src/writer/hlsl/generator_impl_function_entry_point_data_test.cc
+++ b/src/writer/hlsl/generator_impl_function_entry_point_data_test.cc
@@ -53,16 +53,16 @@
   ast::type::F32Type f32;
   ast::type::I32Type i32;
 
-  auto foo_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("foo", ast::StorageClass::kInput, &f32));
+  auto foo_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("foo", ast::StorageClass::kInput, &f32));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::LocationDecoration>(0, Source{}));
+  decos.push_back(create<ast::LocationDecoration>(0, Source{}));
   foo_var->set_decorations(std::move(decos));
 
-  auto bar_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("bar", ast::StorageClass::kInput, &i32));
-  decos.push_back(std::make_unique<ast::LocationDecoration>(1, Source{}));
+  auto bar_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("bar", ast::StorageClass::kInput, &i32));
+  decos.push_back(create<ast::LocationDecoration>(1, Source{}));
   bar_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(foo_var.get());
@@ -72,19 +72,18 @@
   mod.AddGlobalVariable(std::move(bar_var));
 
   ast::VariableList params;
-  auto func =
-      std::make_unique<ast::Function>("vtx_main", std::move(params), &f32);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kVertex, Source{}));
+  auto func = create<ast::Function>("vtx_main", std::move(params), &f32);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
   auto* func_ptr = func.get();
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("foo"),
-      std::make_unique<ast::IdentifierExpression>("foo")));
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("bar"),
-      std::make_unique<ast::IdentifierExpression>("bar")));
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("foo"),
+      create<ast::IdentifierExpression>("foo")));
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("bar"),
+      create<ast::IdentifierExpression>("bar")));
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -114,16 +113,16 @@
   ast::type::F32Type f32;
   ast::type::I32Type i32;
 
-  auto foo_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("foo", ast::StorageClass::kOutput, &f32));
+  auto foo_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("foo", ast::StorageClass::kOutput, &f32));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::LocationDecoration>(0, Source{}));
+  decos.push_back(create<ast::LocationDecoration>(0, Source{}));
   foo_var->set_decorations(std::move(decos));
 
-  auto bar_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("bar", ast::StorageClass::kOutput, &i32));
-  decos.push_back(std::make_unique<ast::LocationDecoration>(1, Source{}));
+  auto bar_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("bar", ast::StorageClass::kOutput, &i32));
+  decos.push_back(create<ast::LocationDecoration>(1, Source{}));
   bar_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(foo_var.get());
@@ -133,19 +132,18 @@
   mod.AddGlobalVariable(std::move(bar_var));
 
   ast::VariableList params;
-  auto func =
-      std::make_unique<ast::Function>("vtx_main", std::move(params), &f32);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kVertex, Source{}));
+  auto func = create<ast::Function>("vtx_main", std::move(params), &f32);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
   auto* func_ptr = func.get();
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("foo"),
-      std::make_unique<ast::IdentifierExpression>("foo")));
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("bar"),
-      std::make_unique<ast::IdentifierExpression>("bar")));
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("foo"),
+      create<ast::IdentifierExpression>("foo")));
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("bar"),
+      create<ast::IdentifierExpression>("bar")));
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -175,16 +173,16 @@
   ast::type::F32Type f32;
   ast::type::I32Type i32;
 
-  auto foo_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("foo", ast::StorageClass::kInput, &f32));
+  auto foo_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("foo", ast::StorageClass::kInput, &f32));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::LocationDecoration>(0, Source{}));
+  decos.push_back(create<ast::LocationDecoration>(0, Source{}));
   foo_var->set_decorations(std::move(decos));
 
-  auto bar_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("bar", ast::StorageClass::kInput, &i32));
-  decos.push_back(std::make_unique<ast::LocationDecoration>(1, Source{}));
+  auto bar_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("bar", ast::StorageClass::kInput, &i32));
+  decos.push_back(create<ast::LocationDecoration>(1, Source{}));
   bar_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(foo_var.get());
@@ -194,18 +192,18 @@
   mod.AddGlobalVariable(std::move(bar_var));
 
   ast::VariableList params;
-  auto func = std::make_unique<ast::Function>("main", std::move(params), &f32);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kVertex, Source{}));
+  auto func = create<ast::Function>("main", std::move(params), &f32);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kVertex, Source{}));
   auto* func_ptr = func.get();
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("foo"),
-      std::make_unique<ast::IdentifierExpression>("foo")));
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("bar"),
-      std::make_unique<ast::IdentifierExpression>("bar")));
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("foo"),
+      create<ast::IdentifierExpression>("foo")));
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("bar"),
+      create<ast::IdentifierExpression>("bar")));
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -235,16 +233,16 @@
   ast::type::F32Type f32;
   ast::type::I32Type i32;
 
-  auto foo_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("foo", ast::StorageClass::kOutput, &f32));
+  auto foo_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("foo", ast::StorageClass::kOutput, &f32));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::LocationDecoration>(0, Source{}));
+  decos.push_back(create<ast::LocationDecoration>(0, Source{}));
   foo_var->set_decorations(std::move(decos));
 
-  auto bar_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("bar", ast::StorageClass::kOutput, &i32));
-  decos.push_back(std::make_unique<ast::LocationDecoration>(1, Source{}));
+  auto bar_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("bar", ast::StorageClass::kOutput, &i32));
+  decos.push_back(create<ast::LocationDecoration>(1, Source{}));
   bar_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(foo_var.get());
@@ -254,18 +252,18 @@
   mod.AddGlobalVariable(std::move(bar_var));
 
   ast::VariableList params;
-  auto func = std::make_unique<ast::Function>("main", std::move(params), &f32);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kFragment, Source{}));
+  auto func = create<ast::Function>("main", std::move(params), &f32);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
   auto* func_ptr = func.get();
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("foo"),
-      std::make_unique<ast::IdentifierExpression>("foo")));
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("bar"),
-      std::make_unique<ast::IdentifierExpression>("bar")));
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("foo"),
+      create<ast::IdentifierExpression>("foo")));
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("bar"),
+      create<ast::IdentifierExpression>("bar")));
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -292,16 +290,16 @@
   ast::type::F32Type f32;
   ast::type::I32Type i32;
 
-  auto foo_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("foo", ast::StorageClass::kInput, &f32));
+  auto foo_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("foo", ast::StorageClass::kInput, &f32));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::LocationDecoration>(0, Source{}));
+  decos.push_back(create<ast::LocationDecoration>(0, Source{}));
   foo_var->set_decorations(std::move(decos));
 
-  auto bar_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("bar", ast::StorageClass::kInput, &i32));
-  decos.push_back(std::make_unique<ast::LocationDecoration>(1, Source{}));
+  auto bar_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("bar", ast::StorageClass::kInput, &i32));
+  decos.push_back(create<ast::LocationDecoration>(1, Source{}));
   bar_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(foo_var.get());
@@ -311,18 +309,18 @@
   mod.AddGlobalVariable(std::move(bar_var));
 
   ast::VariableList params;
-  auto func = std::make_unique<ast::Function>("main", std::move(params), &f32);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kCompute, Source{}));
+  auto func = create<ast::Function>("main", std::move(params), &f32);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
   auto* func_ptr = func.get();
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("foo"),
-      std::make_unique<ast::IdentifierExpression>("foo")));
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("bar"),
-      std::make_unique<ast::IdentifierExpression>("bar")));
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("foo"),
+      create<ast::IdentifierExpression>("foo")));
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("bar"),
+      create<ast::IdentifierExpression>("bar")));
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -344,16 +342,16 @@
   ast::type::F32Type f32;
   ast::type::I32Type i32;
 
-  auto foo_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("foo", ast::StorageClass::kOutput, &f32));
+  auto foo_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("foo", ast::StorageClass::kOutput, &f32));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::LocationDecoration>(0, Source{}));
+  decos.push_back(create<ast::LocationDecoration>(0, Source{}));
   foo_var->set_decorations(std::move(decos));
 
-  auto bar_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("bar", ast::StorageClass::kOutput, &i32));
-  decos.push_back(std::make_unique<ast::LocationDecoration>(1, Source{}));
+  auto bar_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("bar", ast::StorageClass::kOutput, &i32));
+  decos.push_back(create<ast::LocationDecoration>(1, Source{}));
   bar_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(foo_var.get());
@@ -363,18 +361,18 @@
   mod.AddGlobalVariable(std::move(bar_var));
 
   ast::VariableList params;
-  auto func = std::make_unique<ast::Function>("main", std::move(params), &f32);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kCompute, Source{}));
+  auto func = create<ast::Function>("main", std::move(params), &f32);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
   auto* func_ptr = func.get();
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("foo"),
-      std::make_unique<ast::IdentifierExpression>("foo")));
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("bar"),
-      std::make_unique<ast::IdentifierExpression>("bar")));
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("foo"),
+      create<ast::IdentifierExpression>("foo")));
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("bar"),
+      create<ast::IdentifierExpression>("bar")));
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -403,20 +401,18 @@
   ast::type::VoidType void_type;
   ast::type::VectorType vec4(&f32, 4);
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "coord", ast::StorageClass::kInput, &vec4));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("coord", ast::StorageClass::kInput, &vec4));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::BuiltinDecoration>(
-      ast::Builtin::kFragCoord, Source{}));
+  decos.push_back(
+      create<ast::BuiltinDecoration>(ast::Builtin::kFragCoord, Source{}));
   coord_var->set_decorations(std::move(decos));
 
-  auto depth_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "depth", ast::StorageClass::kOutput, &f32));
-  decos.push_back(std::make_unique<ast::BuiltinDecoration>(
-      ast::Builtin::kFragDepth, Source{}));
+  auto depth_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("depth", ast::StorageClass::kOutput, &f32));
+  decos.push_back(
+      create<ast::BuiltinDecoration>(ast::Builtin::kFragDepth, Source{}));
   depth_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(coord_var.get());
@@ -426,18 +422,17 @@
   mod.AddGlobalVariable(std::move(depth_var));
 
   ast::VariableList params;
-  auto func =
-      std::make_unique<ast::Function>("main", std::move(params), &void_type);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kFragment, Source{}));
+  auto func = create<ast::Function>("main", std::move(params), &void_type);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
   auto* func_ptr = func.get();
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("depth"),
-      std::make_unique<ast::MemberAccessorExpression>(
-          std::make_unique<ast::IdentifierExpression>("coord"),
-          std::make_unique<ast::IdentifierExpression>("x"))));
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("depth"),
+      create<ast::MemberAccessorExpression>(
+          create<ast::IdentifierExpression>("coord"),
+          create<ast::IdentifierExpression>("x"))));
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
diff --git a/src/writer/hlsl/generator_impl_function_test.cc b/src/writer/hlsl/generator_impl_function_test.cc
index 3df6492..a4e9df3 100644
--- a/src/writer/hlsl/generator_impl_function_test.cc
+++ b/src/writer/hlsl/generator_impl_function_test.cc
@@ -57,11 +57,10 @@
 TEST_F(HlslGeneratorImplTest_Function, Emit_Function) {
   ast::type::VoidType void_type;
 
-  auto func = std::make_unique<ast::Function>("my_func", ast::VariableList{},
-                                              &void_type);
+  auto func = create<ast::Function>("my_func", ast::VariableList{}, &void_type);
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::ReturnStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::ReturnStatement>());
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -78,11 +77,11 @@
 TEST_F(HlslGeneratorImplTest_Function, Emit_Function_Name_Collision) {
   ast::type::VoidType void_type;
 
-  auto func = std::make_unique<ast::Function>("GeometryShader",
-                                              ast::VariableList{}, &void_type);
+  auto func =
+      create<ast::Function>("GeometryShader", ast::VariableList{}, &void_type);
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::ReturnStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::ReturnStatement>());
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -101,17 +100,14 @@
   ast::type::I32Type i32;
 
   ast::VariableList params;
-  params.push_back(
-      std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &f32));
-  params.push_back(
-      std::make_unique<ast::Variable>("b", ast::StorageClass::kNone, &i32));
+  params.push_back(create<ast::Variable>("a", ast::StorageClass::kNone, &f32));
+  params.push_back(create<ast::Variable>("b", ast::StorageClass::kNone, &i32));
 
   ast::type::VoidType void_type;
-  auto func =
-      std::make_unique<ast::Function>("my_func", std::move(params), &void_type);
+  auto func = create<ast::Function>("my_func", std::move(params), &void_type);
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::ReturnStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::ReturnStatement>());
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -130,16 +126,16 @@
   ast::type::VoidType void_type;
   ast::type::F32Type f32;
 
-  auto foo_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("foo", ast::StorageClass::kInput, &f32));
+  auto foo_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("foo", ast::StorageClass::kInput, &f32));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::LocationDecoration>(0, Source{}));
+  decos.push_back(create<ast::LocationDecoration>(0, Source{}));
   foo_var->set_decorations(std::move(decos));
 
-  auto bar_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("bar", ast::StorageClass::kOutput, &f32));
-  decos.push_back(std::make_unique<ast::LocationDecoration>(1, Source{}));
+  auto bar_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("bar", ast::StorageClass::kOutput, &f32));
+  decos.push_back(create<ast::LocationDecoration>(1, Source{}));
   bar_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(foo_var.get());
@@ -149,16 +145,15 @@
   mod.AddGlobalVariable(std::move(bar_var));
 
   ast::VariableList params;
-  auto func = std::make_unique<ast::Function>("frag_main", std::move(params),
-                                              &void_type);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kFragment, Source{}));
+  auto func = create<ast::Function>("frag_main", std::move(params), &void_type);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("bar"),
-      std::make_unique<ast::IdentifierExpression>("foo")));
-  body->append(std::make_unique<ast::ReturnStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("bar"),
+      create<ast::IdentifierExpression>("foo")));
+  body->append(create<ast::ReturnStatement>());
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -188,20 +183,18 @@
   ast::type::F32Type f32;
   ast::type::VectorType vec4(&f32, 4);
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "coord", ast::StorageClass::kInput, &vec4));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("coord", ast::StorageClass::kInput, &vec4));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::BuiltinDecoration>(
-      ast::Builtin::kFragCoord, Source{}));
+  decos.push_back(
+      create<ast::BuiltinDecoration>(ast::Builtin::kFragCoord, Source{}));
   coord_var->set_decorations(std::move(decos));
 
-  auto depth_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "depth", ast::StorageClass::kOutput, &f32));
-  decos.push_back(std::make_unique<ast::BuiltinDecoration>(
-      ast::Builtin::kFragDepth, Source{}));
+  auto depth_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("depth", ast::StorageClass::kOutput, &f32));
+  decos.push_back(
+      create<ast::BuiltinDecoration>(ast::Builtin::kFragDepth, Source{}));
   depth_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(coord_var.get());
@@ -211,18 +204,17 @@
   mod.AddGlobalVariable(std::move(depth_var));
 
   ast::VariableList params;
-  auto func = std::make_unique<ast::Function>("frag_main", std::move(params),
-                                              &void_type);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kFragment, Source{}));
+  auto func = create<ast::Function>("frag_main", std::move(params), &void_type);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("depth"),
-      std::make_unique<ast::MemberAccessorExpression>(
-          std::make_unique<ast::IdentifierExpression>("coord"),
-          std::make_unique<ast::IdentifierExpression>("x"))));
-  body->append(std::make_unique<ast::ReturnStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("depth"),
+      create<ast::MemberAccessorExpression>(
+          create<ast::IdentifierExpression>("coord"),
+          create<ast::IdentifierExpression>("x"))));
+  body->append(create<ast::ReturnStatement>());
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -252,33 +244,30 @@
   ast::type::F32Type f32;
   ast::type::VectorType vec4(&f32, 4);
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "coord", ast::StorageClass::kUniform, &vec4));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("coord", ast::StorageClass::kUniform, &vec4));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::BindingDecoration>(0, Source{}));
-  decos.push_back(std::make_unique<ast::SetDecoration>(1, Source{}));
+  decos.push_back(create<ast::BindingDecoration>(0, Source{}));
+  decos.push_back(create<ast::SetDecoration>(1, Source{}));
   coord_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(coord_var.get());
   mod.AddGlobalVariable(std::move(coord_var));
 
   ast::VariableList params;
-  auto func = std::make_unique<ast::Function>("frag_main", std::move(params),
-                                              &void_type);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kFragment, Source{}));
+  auto func = create<ast::Function>("frag_main", std::move(params), &void_type);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
 
-  auto var =
-      std::make_unique<ast::Variable>("v", ast::StorageClass::kFunction, &f32);
-  var->set_constructor(std::make_unique<ast::MemberAccessorExpression>(
-      std::make_unique<ast::IdentifierExpression>("coord"),
-      std::make_unique<ast::IdentifierExpression>("x")));
+  auto var = create<ast::Variable>("v", ast::StorageClass::kFunction, &f32);
+  var->set_constructor(create<ast::MemberAccessorExpression>(
+      create<ast::IdentifierExpression>("coord"),
+      create<ast::IdentifierExpression>("x")));
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
-  body->append(std::make_unique<ast::ReturnStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::VariableDeclStatement>(std::move(var)));
+  body->append(create<ast::ReturnStatement>());
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -304,45 +293,42 @@
   ast::type::VectorType vec4(&f32, 4);
 
   ast::StructMemberList members;
-  members.push_back(std::make_unique<ast::StructMember>(
+  members.push_back(create<ast::StructMember>(
       "coord", &vec4, ast::StructMemberDecorationList{}));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Uniforms", std::move(str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "uniforms", ast::StorageClass::kUniform, &s));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("uniforms", ast::StorageClass::kUniform, &s));
 
   mod.AddConstructedType(&s);
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::BindingDecoration>(0, Source{}));
-  decos.push_back(std::make_unique<ast::SetDecoration>(1, Source{}));
+  decos.push_back(create<ast::BindingDecoration>(0, Source{}));
+  decos.push_back(create<ast::SetDecoration>(1, Source{}));
   coord_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(coord_var.get());
   mod.AddGlobalVariable(std::move(coord_var));
 
   ast::VariableList params;
-  auto func = std::make_unique<ast::Function>("frag_main", std::move(params),
-                                              &void_type);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kFragment, Source{}));
+  auto func = create<ast::Function>("frag_main", std::move(params), &void_type);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
 
-  auto var =
-      std::make_unique<ast::Variable>("v", ast::StorageClass::kFunction, &f32);
-  var->set_constructor(std::make_unique<ast::MemberAccessorExpression>(
-      std::make_unique<ast::MemberAccessorExpression>(
-          std::make_unique<ast::IdentifierExpression>("uniforms"),
-          std::make_unique<ast::IdentifierExpression>("coord")),
-      std::make_unique<ast::IdentifierExpression>("x")));
+  auto var = create<ast::Variable>("v", ast::StorageClass::kFunction, &f32);
+  var->set_constructor(create<ast::MemberAccessorExpression>(
+      create<ast::MemberAccessorExpression>(
+          create<ast::IdentifierExpression>("uniforms"),
+          create<ast::IdentifierExpression>("coord")),
+      create<ast::IdentifierExpression>("x")));
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
-  body->append(std::make_unique<ast::ReturnStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::VariableDeclStatement>(std::move(var)));
+  body->append(create<ast::ReturnStatement>());
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -371,50 +357,43 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &i32, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &i32, std::move(a_deco)));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(4, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(4, Source{}));
+  members.push_back(create<ast::StructMember>("b", &f32, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
   ast::type::AccessControlType ac(ast::AccessControl::kReadWrite, &s);
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "coord", ast::StorageClass::kStorageBuffer, &ac));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("coord", ast::StorageClass::kStorageBuffer, &ac));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::BindingDecoration>(0, Source{}));
-  decos.push_back(std::make_unique<ast::SetDecoration>(1, Source{}));
+  decos.push_back(create<ast::BindingDecoration>(0, Source{}));
+  decos.push_back(create<ast::SetDecoration>(1, Source{}));
   coord_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(coord_var.get());
   mod.AddGlobalVariable(std::move(coord_var));
 
   ast::VariableList params;
-  auto func = std::make_unique<ast::Function>("frag_main", std::move(params),
-                                              &void_type);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kFragment, Source{}));
+  auto func = create<ast::Function>("frag_main", std::move(params), &void_type);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
 
-  auto var =
-      std::make_unique<ast::Variable>("v", ast::StorageClass::kFunction, &f32);
-  var->set_constructor(std::make_unique<ast::MemberAccessorExpression>(
-      std::make_unique<ast::IdentifierExpression>("coord"),
-      std::make_unique<ast::IdentifierExpression>("b")));
+  auto var = create<ast::Variable>("v", ast::StorageClass::kFunction, &f32);
+  var->set_constructor(create<ast::MemberAccessorExpression>(
+      create<ast::IdentifierExpression>("coord"),
+      create<ast::IdentifierExpression>("b")));
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
-  body->append(std::make_unique<ast::ReturnStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::VariableDeclStatement>(std::move(var)));
+  body->append(create<ast::ReturnStatement>());
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -439,50 +418,43 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &i32, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &i32, std::move(a_deco)));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(4, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(4, Source{}));
+  members.push_back(create<ast::StructMember>("b", &f32, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
   ast::type::AccessControlType ac(ast::AccessControl::kReadOnly, &s);
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "coord", ast::StorageClass::kStorageBuffer, &ac));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("coord", ast::StorageClass::kStorageBuffer, &ac));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::BindingDecoration>(0, Source{}));
-  decos.push_back(std::make_unique<ast::SetDecoration>(1, Source{}));
+  decos.push_back(create<ast::BindingDecoration>(0, Source{}));
+  decos.push_back(create<ast::SetDecoration>(1, Source{}));
   coord_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(coord_var.get());
   mod.AddGlobalVariable(std::move(coord_var));
 
   ast::VariableList params;
-  auto func = std::make_unique<ast::Function>("frag_main", std::move(params),
-                                              &void_type);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kFragment, Source{}));
+  auto func = create<ast::Function>("frag_main", std::move(params), &void_type);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
 
-  auto var =
-      std::make_unique<ast::Variable>("v", ast::StorageClass::kFunction, &f32);
-  var->set_constructor(std::make_unique<ast::MemberAccessorExpression>(
-      std::make_unique<ast::IdentifierExpression>("coord"),
-      std::make_unique<ast::IdentifierExpression>("b")));
+  auto var = create<ast::Variable>("v", ast::StorageClass::kFunction, &f32);
+  var->set_constructor(create<ast::MemberAccessorExpression>(
+      create<ast::IdentifierExpression>("coord"),
+      create<ast::IdentifierExpression>("b")));
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
-  body->append(std::make_unique<ast::ReturnStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::VariableDeclStatement>(std::move(var)));
+  body->append(create<ast::ReturnStatement>());
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -507,30 +479,25 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &i32, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &i32, std::move(a_deco)));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(4, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(4, Source{}));
+  members.push_back(create<ast::StructMember>("b", &f32, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
   ast::type::AccessControlType ac(ast::AccessControl::kReadWrite, &s);
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "coord", ast::StorageClass::kStorageBuffer, &ac));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("coord", ast::StorageClass::kStorageBuffer, &ac));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::BindingDecoration>(0, Source{}));
-  decos.push_back(std::make_unique<ast::SetDecoration>(1, Source{}));
+  decos.push_back(create<ast::BindingDecoration>(0, Source{}));
+  decos.push_back(create<ast::SetDecoration>(1, Source{}));
   coord_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(coord_var.get());
@@ -538,21 +505,20 @@
   mod.AddGlobalVariable(std::move(coord_var));
 
   ast::VariableList params;
-  auto func = std::make_unique<ast::Function>("frag_main", std::move(params),
-                                              &void_type);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kFragment, Source{}));
+  auto func = create<ast::Function>("frag_main", std::move(params), &void_type);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
 
-  auto assign = std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::MemberAccessorExpression>(
-          std::make_unique<ast::IdentifierExpression>("coord"),
-          std::make_unique<ast::IdentifierExpression>("b")),
-      std::make_unique<ast::ScalarConstructorExpression>(
-          std::make_unique<ast::FloatLiteral>(&f32, 2.0f)));
+  auto assign = create<ast::AssignmentStatement>(
+      create<ast::MemberAccessorExpression>(
+          create<ast::IdentifierExpression>("coord"),
+          create<ast::IdentifierExpression>("b")),
+      create<ast::ScalarConstructorExpression>(
+          create<ast::FloatLiteral>(&f32, 2.0f)));
 
-  auto body = std::make_unique<ast::BlockStatement>();
+  auto body = create<ast::BlockStatement>();
   body->append(std::move(assign));
-  body->append(std::make_unique<ast::ReturnStatement>());
+  body->append(create<ast::ReturnStatement>());
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -575,21 +541,21 @@
   ast::type::VoidType void_type;
   ast::type::F32Type f32;
 
-  auto foo_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("foo", ast::StorageClass::kInput, &f32));
+  auto foo_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("foo", ast::StorageClass::kInput, &f32));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::LocationDecoration>(0, Source{}));
+  decos.push_back(create<ast::LocationDecoration>(0, Source{}));
   foo_var->set_decorations(std::move(decos));
 
-  auto bar_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("bar", ast::StorageClass::kOutput, &f32));
-  decos.push_back(std::make_unique<ast::LocationDecoration>(1, Source{}));
+  auto bar_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("bar", ast::StorageClass::kOutput, &f32));
+  decos.push_back(create<ast::LocationDecoration>(1, Source{}));
   bar_var->set_decorations(std::move(decos));
 
-  auto val_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("val", ast::StorageClass::kOutput, &f32));
-  decos.push_back(std::make_unique<ast::LocationDecoration>(0, Source{}));
+  auto val_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("val", ast::StorageClass::kOutput, &f32));
+  decos.push_back(create<ast::LocationDecoration>(0, Source{}));
   val_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(foo_var.get());
@@ -601,40 +567,37 @@
   mod.AddGlobalVariable(std::move(val_var));
 
   ast::VariableList params;
-  params.push_back(std::make_unique<ast::Variable>(
-      "param", ast::StorageClass::kFunction, &f32));
-  auto sub_func =
-      std::make_unique<ast::Function>("sub_func", std::move(params), &f32);
+  params.push_back(
+      create<ast::Variable>("param", ast::StorageClass::kFunction, &f32));
+  auto sub_func = create<ast::Function>("sub_func", std::move(params), &f32);
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("bar"),
-      std::make_unique<ast::IdentifierExpression>("foo")));
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("val"),
-      std::make_unique<ast::IdentifierExpression>("param")));
-  body->append(std::make_unique<ast::ReturnStatement>(
-      std::make_unique<ast::IdentifierExpression>("foo")));
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("bar"),
+      create<ast::IdentifierExpression>("foo")));
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("val"),
+      create<ast::IdentifierExpression>("param")));
+  body->append(
+      create<ast::ReturnStatement>(create<ast::IdentifierExpression>("foo")));
   sub_func->set_body(std::move(body));
 
   mod.AddFunction(std::move(sub_func));
 
-  auto func_1 =
-      std::make_unique<ast::Function>("ep_1", std::move(params), &void_type);
-  func_1->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kFragment, Source{}));
+  auto func_1 = create<ast::Function>("ep_1", std::move(params), &void_type);
+  func_1->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
 
   ast::ExpressionList expr;
-  expr.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 1.0f)));
+  expr.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 1.0f)));
 
-  body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("bar"),
-      std::make_unique<ast::CallExpression>(
-          std::make_unique<ast::IdentifierExpression>("sub_func"),
-          std::move(expr))));
-  body->append(std::make_unique<ast::ReturnStatement>());
+  body = create<ast::BlockStatement>();
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("bar"),
+      create<ast::CallExpression>(create<ast::IdentifierExpression>("sub_func"),
+                                  std::move(expr))));
+  body->append(create<ast::ReturnStatement>());
   func_1->set_body(std::move(body));
 
   mod.AddFunction(std::move(func_1));
@@ -671,13 +634,12 @@
   ast::type::F32Type f32;
   ast::type::VectorType vec4(&f32, 4);
 
-  auto depth_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "depth", ast::StorageClass::kOutput, &f32));
+  auto depth_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("depth", ast::StorageClass::kOutput, &f32));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::BuiltinDecoration>(
-      ast::Builtin::kFragDepth, Source{}));
+  decos.push_back(
+      create<ast::BuiltinDecoration>(ast::Builtin::kFragDepth, Source{}));
   depth_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(depth_var.get());
@@ -685,34 +647,31 @@
   mod.AddGlobalVariable(std::move(depth_var));
 
   ast::VariableList params;
-  params.push_back(std::make_unique<ast::Variable>(
-      "param", ast::StorageClass::kFunction, &f32));
-  auto sub_func =
-      std::make_unique<ast::Function>("sub_func", std::move(params), &f32);
+  params.push_back(
+      create<ast::Variable>("param", ast::StorageClass::kFunction, &f32));
+  auto sub_func = create<ast::Function>("sub_func", std::move(params), &f32);
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::ReturnStatement>(
-      std::make_unique<ast::IdentifierExpression>("param")));
+  auto body = create<ast::BlockStatement>();
+  body->append(
+      create<ast::ReturnStatement>(create<ast::IdentifierExpression>("param")));
   sub_func->set_body(std::move(body));
 
   mod.AddFunction(std::move(sub_func));
 
-  auto func_1 =
-      std::make_unique<ast::Function>("ep_1", std::move(params), &void_type);
-  func_1->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kFragment, Source{}));
+  auto func_1 = create<ast::Function>("ep_1", std::move(params), &void_type);
+  func_1->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
 
   ast::ExpressionList expr;
-  expr.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 1.0f)));
+  expr.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 1.0f)));
 
-  body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("depth"),
-      std::make_unique<ast::CallExpression>(
-          std::make_unique<ast::IdentifierExpression>("sub_func"),
-          std::move(expr))));
-  body->append(std::make_unique<ast::ReturnStatement>());
+  body = create<ast::BlockStatement>();
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("depth"),
+      create<ast::CallExpression>(create<ast::IdentifierExpression>("sub_func"),
+                                  std::move(expr))));
+  body->append(create<ast::ReturnStatement>());
   func_1->set_body(std::move(body));
 
   mod.AddFunction(std::move(func_1));
@@ -743,20 +702,18 @@
   ast::type::F32Type f32;
   ast::type::VectorType vec4(&f32, 4);
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "coord", ast::StorageClass::kInput, &vec4));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("coord", ast::StorageClass::kInput, &vec4));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::BuiltinDecoration>(
-      ast::Builtin::kFragCoord, Source{}));
+  decos.push_back(
+      create<ast::BuiltinDecoration>(ast::Builtin::kFragCoord, Source{}));
   coord_var->set_decorations(std::move(decos));
 
-  auto depth_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "depth", ast::StorageClass::kOutput, &f32));
-  decos.push_back(std::make_unique<ast::BuiltinDecoration>(
-      ast::Builtin::kFragDepth, Source{}));
+  auto depth_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("depth", ast::StorageClass::kOutput, &f32));
+  decos.push_back(
+      create<ast::BuiltinDecoration>(ast::Builtin::kFragDepth, Source{}));
   depth_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(coord_var.get());
@@ -766,39 +723,36 @@
   mod.AddGlobalVariable(std::move(depth_var));
 
   ast::VariableList params;
-  params.push_back(std::make_unique<ast::Variable>(
-      "param", ast::StorageClass::kFunction, &f32));
-  auto sub_func =
-      std::make_unique<ast::Function>("sub_func", std::move(params), &f32);
+  params.push_back(
+      create<ast::Variable>("param", ast::StorageClass::kFunction, &f32));
+  auto sub_func = create<ast::Function>("sub_func", std::move(params), &f32);
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("depth"),
-      std::make_unique<ast::MemberAccessorExpression>(
-          std::make_unique<ast::IdentifierExpression>("coord"),
-          std::make_unique<ast::IdentifierExpression>("x"))));
-  body->append(std::make_unique<ast::ReturnStatement>(
-      std::make_unique<ast::IdentifierExpression>("param")));
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("depth"),
+      create<ast::MemberAccessorExpression>(
+          create<ast::IdentifierExpression>("coord"),
+          create<ast::IdentifierExpression>("x"))));
+  body->append(
+      create<ast::ReturnStatement>(create<ast::IdentifierExpression>("param")));
   sub_func->set_body(std::move(body));
 
   mod.AddFunction(std::move(sub_func));
 
-  auto func_1 =
-      std::make_unique<ast::Function>("ep_1", std::move(params), &void_type);
-  func_1->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kFragment, Source{}));
+  auto func_1 = create<ast::Function>("ep_1", std::move(params), &void_type);
+  func_1->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
 
   ast::ExpressionList expr;
-  expr.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 1.0f)));
+  expr.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 1.0f)));
 
-  body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("depth"),
-      std::make_unique<ast::CallExpression>(
-          std::make_unique<ast::IdentifierExpression>("sub_func"),
-          std::move(expr))));
-  body->append(std::make_unique<ast::ReturnStatement>());
+  body = create<ast::BlockStatement>();
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("depth"),
+      create<ast::CallExpression>(create<ast::IdentifierExpression>("sub_func"),
+                                  std::move(expr))));
+  body->append(create<ast::ReturnStatement>());
   func_1->set_body(std::move(body));
 
   mod.AddFunction(std::move(func_1));
@@ -833,13 +787,12 @@
   ast::type::F32Type f32;
   ast::type::VectorType vec4(&f32, 4);
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "coord", ast::StorageClass::kUniform, &vec4));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("coord", ast::StorageClass::kUniform, &vec4));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::BindingDecoration>(0, Source{}));
-  decos.push_back(std::make_unique<ast::SetDecoration>(1, Source{}));
+  decos.push_back(create<ast::BindingDecoration>(0, Source{}));
+  decos.push_back(create<ast::SetDecoration>(1, Source{}));
   coord_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(coord_var.get());
@@ -847,38 +800,34 @@
   mod.AddGlobalVariable(std::move(coord_var));
 
   ast::VariableList params;
-  params.push_back(std::make_unique<ast::Variable>(
-      "param", ast::StorageClass::kFunction, &f32));
-  auto sub_func =
-      std::make_unique<ast::Function>("sub_func", std::move(params), &f32);
+  params.push_back(
+      create<ast::Variable>("param", ast::StorageClass::kFunction, &f32));
+  auto sub_func = create<ast::Function>("sub_func", std::move(params), &f32);
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::ReturnStatement>(
-      std::make_unique<ast::MemberAccessorExpression>(
-          std::make_unique<ast::IdentifierExpression>("coord"),
-          std::make_unique<ast::IdentifierExpression>("x"))));
+  auto body = create<ast::BlockStatement>();
+  body->append(
+      create<ast::ReturnStatement>(create<ast::MemberAccessorExpression>(
+          create<ast::IdentifierExpression>("coord"),
+          create<ast::IdentifierExpression>("x"))));
   sub_func->set_body(std::move(body));
 
   mod.AddFunction(std::move(sub_func));
 
-  auto func = std::make_unique<ast::Function>("frag_main", std::move(params),
-                                              &void_type);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kFragment, Source{}));
+  auto func = create<ast::Function>("frag_main", std::move(params), &void_type);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
 
   ast::ExpressionList expr;
-  expr.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 1.0f)));
+  expr.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 1.0f)));
 
-  auto var =
-      std::make_unique<ast::Variable>("v", ast::StorageClass::kFunction, &f32);
-  var->set_constructor(std::make_unique<ast::CallExpression>(
-      std::make_unique<ast::IdentifierExpression>("sub_func"),
-      std::move(expr)));
+  auto var = create<ast::Variable>("v", ast::StorageClass::kFunction, &f32);
+  var->set_constructor(create<ast::CallExpression>(
+      create<ast::IdentifierExpression>("sub_func"), std::move(expr)));
 
-  body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
-  body->append(std::make_unique<ast::ReturnStatement>());
+  body = create<ast::BlockStatement>();
+  body->append(create<ast::VariableDeclStatement>(std::move(var)));
+  body->append(create<ast::ReturnStatement>());
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -907,13 +856,12 @@
   ast::type::F32Type f32;
   ast::type::VectorType vec4(&f32, 4);
   ast::type::AccessControlType ac(ast::AccessControl::kReadWrite, &vec4);
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "coord", ast::StorageClass::kStorageBuffer, &ac));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("coord", ast::StorageClass::kStorageBuffer, &ac));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::BindingDecoration>(0, Source{}));
-  decos.push_back(std::make_unique<ast::SetDecoration>(1, Source{}));
+  decos.push_back(create<ast::BindingDecoration>(0, Source{}));
+  decos.push_back(create<ast::SetDecoration>(1, Source{}));
   coord_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(coord_var.get());
@@ -921,38 +869,34 @@
   mod.AddGlobalVariable(std::move(coord_var));
 
   ast::VariableList params;
-  params.push_back(std::make_unique<ast::Variable>(
-      "param", ast::StorageClass::kFunction, &f32));
-  auto sub_func =
-      std::make_unique<ast::Function>("sub_func", std::move(params), &f32);
+  params.push_back(
+      create<ast::Variable>("param", ast::StorageClass::kFunction, &f32));
+  auto sub_func = create<ast::Function>("sub_func", std::move(params), &f32);
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::ReturnStatement>(
-      std::make_unique<ast::MemberAccessorExpression>(
-          std::make_unique<ast::IdentifierExpression>("coord"),
-          std::make_unique<ast::IdentifierExpression>("x"))));
+  auto body = create<ast::BlockStatement>();
+  body->append(
+      create<ast::ReturnStatement>(create<ast::MemberAccessorExpression>(
+          create<ast::IdentifierExpression>("coord"),
+          create<ast::IdentifierExpression>("x"))));
   sub_func->set_body(std::move(body));
 
   mod.AddFunction(std::move(sub_func));
 
-  auto func = std::make_unique<ast::Function>("frag_main", std::move(params),
-                                              &void_type);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kFragment, Source{}));
+  auto func = create<ast::Function>("frag_main", std::move(params), &void_type);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
 
   ast::ExpressionList expr;
-  expr.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 1.0f)));
+  expr.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 1.0f)));
 
-  auto var =
-      std::make_unique<ast::Variable>("v", ast::StorageClass::kFunction, &f32);
-  var->set_constructor(std::make_unique<ast::CallExpression>(
-      std::make_unique<ast::IdentifierExpression>("sub_func"),
-      std::move(expr)));
+  auto var = create<ast::Variable>("v", ast::StorageClass::kFunction, &f32);
+  var->set_constructor(create<ast::CallExpression>(
+      create<ast::IdentifierExpression>("sub_func"), std::move(expr)));
 
-  body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
-  body->append(std::make_unique<ast::ReturnStatement>());
+  body = create<ast::BlockStatement>();
+  body->append(create<ast::VariableDeclStatement>(std::move(var)));
+  body->append(create<ast::ReturnStatement>());
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -979,40 +923,38 @@
   ast::type::F32Type f32;
   ast::type::I32Type i32;
 
-  auto bar_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("bar", ast::StorageClass::kOutput, &f32));
+  auto bar_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("bar", ast::StorageClass::kOutput, &f32));
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::LocationDecoration>(1, Source{}));
+  decos.push_back(create<ast::LocationDecoration>(1, Source{}));
   bar_var->set_decorations(std::move(decos));
 
   td.RegisterVariableForTesting(bar_var.get());
   mod.AddGlobalVariable(std::move(bar_var));
 
   ast::VariableList params;
-  auto func_1 =
-      std::make_unique<ast::Function>("ep_1", std::move(params), &void_type);
-  func_1->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kFragment, Source{}));
+  auto func_1 = create<ast::Function>("ep_1", std::move(params), &void_type);
+  func_1->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::AssignmentStatement>(
-      std::make_unique<ast::IdentifierExpression>("bar"),
-      std::make_unique<ast::ScalarConstructorExpression>(
-          std::make_unique<ast::FloatLiteral>(&f32, 1.0f))));
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::AssignmentStatement>(
+      create<ast::IdentifierExpression>("bar"),
+      create<ast::ScalarConstructorExpression>(
+          create<ast::FloatLiteral>(&f32, 1.0f))));
 
-  auto list = std::make_unique<ast::BlockStatement>();
-  list->append(std::make_unique<ast::ReturnStatement>());
+  auto list = create<ast::BlockStatement>();
+  list->append(create<ast::ReturnStatement>());
 
-  body->append(std::make_unique<ast::IfStatement>(
-      std::make_unique<ast::BinaryExpression>(
-          ast::BinaryOp::kEqual,
-          std::make_unique<ast::ScalarConstructorExpression>(
-              std::make_unique<ast::SintLiteral>(&i32, 1)),
-          std::make_unique<ast::ScalarConstructorExpression>(
-              std::make_unique<ast::SintLiteral>(&i32, 1))),
+  body->append(create<ast::IfStatement>(
+      create<ast::BinaryExpression>(ast::BinaryOp::kEqual,
+                                    create<ast::ScalarConstructorExpression>(
+                                        create<ast::SintLiteral>(&i32, 1)),
+                                    create<ast::ScalarConstructorExpression>(
+                                        create<ast::SintLiteral>(&i32, 1))),
       std::move(list)));
 
-  body->append(std::make_unique<ast::ReturnStatement>());
+  body->append(create<ast::ReturnStatement>());
   func_1->set_body(std::move(body));
 
   mod.AddFunction(std::move(func_1));
@@ -1039,10 +981,10 @@
        Emit_FunctionDecoration_EntryPoint_WithNameCollision) {
   ast::type::VoidType void_type;
 
-  auto func = std::make_unique<ast::Function>("GeometryShader",
-                                              ast::VariableList{}, &void_type);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kFragment, Source{}));
+  auto func =
+      create<ast::Function>("GeometryShader", ast::VariableList{}, &void_type);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kFragment, Source{}));
 
   mod.AddFunction(std::move(func));
 
@@ -1058,13 +1000,12 @@
   ast::type::VoidType void_type;
 
   ast::VariableList params;
-  auto func =
-      std::make_unique<ast::Function>("main", std::move(params), &void_type);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kCompute, Source{}));
+  auto func = create<ast::Function>("main", std::move(params), &void_type);
+  func->add_decoration(
+      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::ReturnStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::ReturnStatement>());
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -1084,15 +1025,13 @@
   ast::type::VoidType void_type;
 
   ast::VariableList params;
-  auto func =
-      std::make_unique<ast::Function>("main", std::move(params), &void_type);
-  func->add_decoration(std::make_unique<ast::StageDecoration>(
-      ast::PipelineStage::kCompute, Source{}));
+  auto func = create<ast::Function>("main", std::move(params), &void_type);
   func->add_decoration(
-      std::make_unique<ast::WorkgroupDecoration>(2u, 4u, 6u, Source{}));
+      create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
+  func->add_decoration(create<ast::WorkgroupDecoration>(2u, 4u, 6u, Source{}));
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::ReturnStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::ReturnStatement>());
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -1112,15 +1051,13 @@
   ast::type::ArrayType ary(&f32, 5);
 
   ast::VariableList params;
-  params.push_back(
-      std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &ary));
+  params.push_back(create<ast::Variable>("a", ast::StorageClass::kNone, &ary));
 
   ast::type::VoidType void_type;
-  auto func =
-      std::make_unique<ast::Function>("my_func", std::move(params), &void_type);
+  auto func = create<ast::Function>("my_func", std::move(params), &void_type);
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::ReturnStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::ReturnStatement>());
   func->set_body(std::move(body));
 
   mod.AddFunction(std::move(func));
@@ -1157,27 +1094,23 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("d", &f32, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("d", &f32, std::move(a_deco)));
 
   ast::StructDecorationList s_decos;
-  s_decos.push_back(std::make_unique<ast::StructBlockDecoration>(Source{}));
+  s_decos.push_back(create<ast::StructBlockDecoration>(Source{}));
 
-  auto str =
-      std::make_unique<ast::Struct>(std::move(s_decos), std::move(members));
+  auto str = create<ast::Struct>(std::move(s_decos), std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
   ast::type::AccessControlType ac(ast::AccessControl::kReadWrite, &s);
 
-  auto data_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &ac));
+  auto data_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("data", ast::StorageClass::kStorageBuffer, &ac));
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::BindingDecoration>(0, Source{}));
-  decos.push_back(std::make_unique<ast::SetDecoration>(0, Source{}));
+  decos.push_back(create<ast::BindingDecoration>(0, Source{}));
+  decos.push_back(create<ast::SetDecoration>(0, Source{}));
   data_var->set_decorations(std::move(decos));
 
   mod.AddConstructedType(&s);
@@ -1186,20 +1119,18 @@
 
   {
     ast::VariableList params;
-    auto func =
-        std::make_unique<ast::Function>("a", std::move(params), &void_type);
-    func->add_decoration(std::make_unique<ast::StageDecoration>(
-        ast::PipelineStage::kCompute, Source{}));
+    auto func = create<ast::Function>("a", std::move(params), &void_type);
+    func->add_decoration(
+        create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
 
-    auto var = std::make_unique<ast::Variable>(
-        "v", ast::StorageClass::kFunction, &f32);
-    var->set_constructor(std::make_unique<ast::MemberAccessorExpression>(
-        std::make_unique<ast::IdentifierExpression>("data"),
-        std::make_unique<ast::IdentifierExpression>("d")));
+    auto var = create<ast::Variable>("v", ast::StorageClass::kFunction, &f32);
+    var->set_constructor(create<ast::MemberAccessorExpression>(
+        create<ast::IdentifierExpression>("data"),
+        create<ast::IdentifierExpression>("d")));
 
-    auto body = std::make_unique<ast::BlockStatement>();
-    body->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
-    body->append(std::make_unique<ast::ReturnStatement>());
+    auto body = create<ast::BlockStatement>();
+    body->append(create<ast::VariableDeclStatement>(std::move(var)));
+    body->append(create<ast::ReturnStatement>());
     func->set_body(std::move(body));
 
     mod.AddFunction(std::move(func));
@@ -1207,20 +1138,18 @@
 
   {
     ast::VariableList params;
-    auto func =
-        std::make_unique<ast::Function>("b", std::move(params), &void_type);
-    func->add_decoration(std::make_unique<ast::StageDecoration>(
-        ast::PipelineStage::kCompute, Source{}));
+    auto func = create<ast::Function>("b", std::move(params), &void_type);
+    func->add_decoration(
+        create<ast::StageDecoration>(ast::PipelineStage::kCompute, Source{}));
 
-    auto var = std::make_unique<ast::Variable>(
-        "v", ast::StorageClass::kFunction, &f32);
-    var->set_constructor(std::make_unique<ast::MemberAccessorExpression>(
-        std::make_unique<ast::IdentifierExpression>("data"),
-        std::make_unique<ast::IdentifierExpression>("d")));
+    auto var = create<ast::Variable>("v", ast::StorageClass::kFunction, &f32);
+    var->set_constructor(create<ast::MemberAccessorExpression>(
+        create<ast::IdentifierExpression>("data"),
+        create<ast::IdentifierExpression>("d")));
 
-    auto body = std::make_unique<ast::BlockStatement>();
-    body->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
-    body->append(std::make_unique<ast::ReturnStatement>());
+    auto body = create<ast::BlockStatement>();
+    body->append(create<ast::VariableDeclStatement>(std::move(var)));
+    body->append(create<ast::ReturnStatement>());
     func->set_body(std::move(body));
 
     mod.AddFunction(std::move(func));
diff --git a/src/writer/hlsl/generator_impl_if_test.cc b/src/writer/hlsl/generator_impl_if_test.cc
index f531cd6..f1a4277 100644
--- a/src/writer/hlsl/generator_impl_if_test.cc
+++ b/src/writer/hlsl/generator_impl_if_test.cc
@@ -27,9 +27,9 @@
 using HlslGeneratorImplTest_If = TestHelper;
 
 TEST_F(HlslGeneratorImplTest_If, Emit_If) {
-  auto cond = std::make_unique<ast::IdentifierExpression>("cond");
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::ReturnStatement>());
+  auto cond = create<ast::IdentifierExpression>("cond");
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::ReturnStatement>());
 
   ast::IfStatement i(std::move(cond), std::move(body));
   gen.increment_indent();
@@ -42,17 +42,17 @@
 }
 
 TEST_F(HlslGeneratorImplTest_If, Emit_IfWithElseIf) {
-  auto else_cond = std::make_unique<ast::IdentifierExpression>("else_cond");
-  auto else_body = std::make_unique<ast::BlockStatement>();
-  else_body->append(std::make_unique<ast::ReturnStatement>());
+  auto else_cond = create<ast::IdentifierExpression>("else_cond");
+  auto else_body = create<ast::BlockStatement>();
+  else_body->append(create<ast::ReturnStatement>());
 
   ast::ElseStatementList elses;
-  elses.push_back(std::make_unique<ast::ElseStatement>(std::move(else_cond),
-                                                       std::move(else_body)));
+  elses.push_back(
+      create<ast::ElseStatement>(std::move(else_cond), std::move(else_body)));
 
-  auto cond = std::make_unique<ast::IdentifierExpression>("cond");
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::ReturnStatement>());
+  auto cond = create<ast::IdentifierExpression>("cond");
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::ReturnStatement>());
 
   ast::IfStatement i(std::move(cond), std::move(body));
   i.set_else_statements(std::move(elses));
@@ -71,15 +71,15 @@
 }
 
 TEST_F(HlslGeneratorImplTest_If, Emit_IfWithElse) {
-  auto else_body = std::make_unique<ast::BlockStatement>();
-  else_body->append(std::make_unique<ast::ReturnStatement>());
+  auto else_body = create<ast::BlockStatement>();
+  else_body->append(create<ast::ReturnStatement>());
 
   ast::ElseStatementList elses;
-  elses.push_back(std::make_unique<ast::ElseStatement>(std::move(else_body)));
+  elses.push_back(create<ast::ElseStatement>(std::move(else_body)));
 
-  auto cond = std::make_unique<ast::IdentifierExpression>("cond");
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::ReturnStatement>());
+  auto cond = create<ast::IdentifierExpression>("cond");
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::ReturnStatement>());
 
   ast::IfStatement i(std::move(cond), std::move(body));
   i.set_else_statements(std::move(elses));
@@ -96,22 +96,22 @@
 }
 
 TEST_F(HlslGeneratorImplTest_If, Emit_IfWithMultiple) {
-  auto else_cond = std::make_unique<ast::IdentifierExpression>("else_cond");
+  auto else_cond = create<ast::IdentifierExpression>("else_cond");
 
-  auto else_body = std::make_unique<ast::BlockStatement>();
-  else_body->append(std::make_unique<ast::ReturnStatement>());
+  auto else_body = create<ast::BlockStatement>();
+  else_body->append(create<ast::ReturnStatement>());
 
-  auto else_body_2 = std::make_unique<ast::BlockStatement>();
-  else_body_2->append(std::make_unique<ast::ReturnStatement>());
+  auto else_body_2 = create<ast::BlockStatement>();
+  else_body_2->append(create<ast::ReturnStatement>());
 
   ast::ElseStatementList elses;
-  elses.push_back(std::make_unique<ast::ElseStatement>(std::move(else_cond),
-                                                       std::move(else_body)));
-  elses.push_back(std::make_unique<ast::ElseStatement>(std::move(else_body_2)));
+  elses.push_back(
+      create<ast::ElseStatement>(std::move(else_cond), std::move(else_body)));
+  elses.push_back(create<ast::ElseStatement>(std::move(else_body_2)));
 
-  auto cond = std::make_unique<ast::IdentifierExpression>("cond");
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::ReturnStatement>());
+  auto cond = create<ast::IdentifierExpression>("cond");
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::ReturnStatement>());
 
   ast::IfStatement i(std::move(cond), std::move(body));
   i.set_else_statements(std::move(elses));
diff --git a/src/writer/hlsl/generator_impl_import_test.cc b/src/writer/hlsl/generator_impl_import_test.cc
index 152a64a..7df6c9e 100644
--- a/src/writer/hlsl/generator_impl_import_test.cc
+++ b/src/writer/hlsl/generator_impl_import_test.cc
@@ -54,10 +54,10 @@
   ast::type::F32Type f32;
 
   ast::ExpressionList params;
-  params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 1.f)));
+  params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 1.f)));
 
-  auto ident = std::make_unique<ast::IdentifierExpression>(param.name);
+  auto ident = create<ast::IdentifierExpression>(param.name);
   ast::CallExpression expr(std::move(ident), std::move(params));
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
@@ -99,12 +99,11 @@
   ast::type::I32Type i32;
 
   ast::ExpressionList params;
-  params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::SintLiteral>(&i32, 1)));
+  params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::SintLiteral>(&i32, 1)));
 
-  ast::CallExpression expr(
-      std::make_unique<ast::IdentifierExpression>(param.name),
-      std::move(params));
+  ast::CallExpression expr(create<ast::IdentifierExpression>(param.name),
+                           std::move(params));
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
   ASSERT_TRUE(gen.EmitCall(pre, out, &expr)) << gen.error();
@@ -121,14 +120,13 @@
   ast::type::F32Type f32;
 
   ast::ExpressionList params;
-  params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 1.f)));
-  params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 2.f)));
+  params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 1.f)));
+  params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 2.f)));
 
-  ast::CallExpression expr(
-      std::make_unique<ast::IdentifierExpression>(param.name),
-      std::move(params));
+  ast::CallExpression expr(create<ast::IdentifierExpression>(param.name),
+                           std::move(params));
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
   ASSERT_TRUE(gen.EmitCall(pre, out, &expr)) << gen.error();
@@ -153,29 +151,28 @@
   ast::type::VectorType vec(&f32, 3);
 
   ast::ExpressionList type_params;
-  type_params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 1.f)));
-  type_params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 2.f)));
-  type_params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 3.f)));
+  type_params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 1.f)));
+  type_params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 2.f)));
+  type_params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 3.f)));
 
   ast::ExpressionList params;
-  params.push_back(std::make_unique<ast::TypeConstructorExpression>(
-      &vec, std::move(type_params)));
+  params.push_back(
+      create<ast::TypeConstructorExpression>(&vec, std::move(type_params)));
 
-  type_params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 4.f)));
-  type_params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 5.f)));
-  type_params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 6.f)));
-  params.push_back(std::make_unique<ast::TypeConstructorExpression>(
-      &vec, std::move(type_params)));
+  type_params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 4.f)));
+  type_params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 5.f)));
+  type_params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 6.f)));
+  params.push_back(
+      create<ast::TypeConstructorExpression>(&vec, std::move(type_params)));
 
-  ast::CallExpression expr(
-      std::make_unique<ast::IdentifierExpression>(param.name),
-      std::move(params));
+  ast::CallExpression expr(create<ast::IdentifierExpression>(param.name),
+                           std::move(params));
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
   ASSERT_TRUE(gen.EmitCall(pre, out, &expr)) << gen.error();
@@ -195,14 +192,13 @@
   ast::type::I32Type i32;
 
   ast::ExpressionList params;
-  params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::SintLiteral>(&i32, 1)));
-  params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::SintLiteral>(&i32, 2)));
+  params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::SintLiteral>(&i32, 1)));
+  params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::SintLiteral>(&i32, 2)));
 
-  ast::CallExpression expr(
-      std::make_unique<ast::IdentifierExpression>(param.name),
-      std::move(params));
+  ast::CallExpression expr(create<ast::IdentifierExpression>(param.name),
+                           std::move(params));
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
   ASSERT_TRUE(gen.EmitCall(pre, out, &expr)) << gen.error();
@@ -220,16 +216,15 @@
   ast::type::F32Type f32;
 
   ast::ExpressionList params;
-  params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 1.f)));
-  params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 2.f)));
-  params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 3.f)));
+  params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 1.f)));
+  params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 2.f)));
+  params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 3.f)));
 
-  ast::CallExpression expr(
-      std::make_unique<ast::IdentifierExpression>(param.name),
-      std::move(params));
+  ast::CallExpression expr(create<ast::IdentifierExpression>(param.name),
+                           std::move(params));
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
   ASSERT_TRUE(gen.EmitCall(pre, out, &expr)) << gen.error();
@@ -255,16 +250,15 @@
   ast::type::I32Type i32;
 
   ast::ExpressionList params;
-  params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::SintLiteral>(&i32, 1)));
-  params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::SintLiteral>(&i32, 2)));
-  params.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::SintLiteral>(&i32, 3)));
+  params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::SintLiteral>(&i32, 1)));
+  params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::SintLiteral>(&i32, 2)));
+  params.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::SintLiteral>(&i32, 3)));
 
-  ast::CallExpression expr(
-      std::make_unique<ast::IdentifierExpression>(param.name),
-      std::move(params));
+  ast::CallExpression expr(create<ast::IdentifierExpression>(param.name),
+                           std::move(params));
 
   ASSERT_TRUE(td.DetermineResultType(&expr)) << td.error();
   ASSERT_TRUE(gen.EmitCall(pre, out, &expr)) << gen.error();
@@ -278,15 +272,13 @@
   ast::type::F32Type f32;
   ast::type::MatrixType mat(&f32, 3, 3);
 
-  auto var = std::make_unique<ast::Variable>(
-      "var", ast::StorageClass::kFunction, &mat);
+  auto var = create<ast::Variable>("var", ast::StorageClass::kFunction, &mat);
 
   ast::ExpressionList params;
-  params.push_back(std::make_unique<ast::IdentifierExpression>("var"));
+  params.push_back(create<ast::IdentifierExpression>("var"));
 
-  ast::CallExpression expr(
-      std::make_unique<ast::IdentifierExpression>("determinant"),
-      std::move(params));
+  ast::CallExpression expr(create<ast::IdentifierExpression>("determinant"),
+                           std::move(params));
 
   mod.AddGlobalVariable(std::move(var));
 
diff --git a/src/writer/hlsl/generator_impl_intrinsic_test.cc b/src/writer/hlsl/generator_impl_intrinsic_test.cc
index 37e4eba..6b4a678 100644
--- a/src/writer/hlsl/generator_impl_intrinsic_test.cc
+++ b/src/writer/hlsl/generator_impl_intrinsic_test.cc
@@ -76,18 +76,15 @@
   ast::type::VectorType vec2(&f32, 2);
   ast::type::VectorType vec3(&f32, 3);
 
-  auto a =
-      std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &vec2);
-  auto b =
-      std::make_unique<ast::Variable>("b", ast::StorageClass::kNone, &vec3);
+  auto a = create<ast::Variable>("a", ast::StorageClass::kNone, &vec2);
+  auto b = create<ast::Variable>("b", ast::StorageClass::kNone, &vec3);
 
   ast::ExpressionList params;
-  params.push_back(std::make_unique<ast::IdentifierExpression>("a"));
-  params.push_back(std::make_unique<ast::IdentifierExpression>("b"));
+  params.push_back(create<ast::IdentifierExpression>("a"));
+  params.push_back(create<ast::IdentifierExpression>("b"));
 
-  ast::CallExpression call(
-      std::make_unique<ast::IdentifierExpression>("outer_product"),
-      std::move(params));
+  ast::CallExpression call(create<ast::IdentifierExpression>("outer_product"),
+                           std::move(params));
 
   td.RegisterVariableForTesting(a.get());
   td.RegisterVariableForTesting(b.get());
@@ -112,10 +109,10 @@
   ast::type::VectorType vec(&f32, 3);
 
   ast::ExpressionList params;
-  params.push_back(std::make_unique<ast::IdentifierExpression>("param1"));
-  params.push_back(std::make_unique<ast::IdentifierExpression>("param2"));
+  params.push_back(create<ast::IdentifierExpression>("param1"));
+  params.push_back(create<ast::IdentifierExpression>("param2"));
 
-  ast::CallExpression call(std::make_unique<ast::IdentifierExpression>("dot"),
+  ast::CallExpression call(create<ast::IdentifierExpression>("dot"),
                            std::move(params));
 
   ast::Variable v1("param1", ast::StorageClass::kFunction, &vec);
diff --git a/src/writer/hlsl/generator_impl_loop_test.cc b/src/writer/hlsl/generator_impl_loop_test.cc
index 7496064..7416cd1 100644
--- a/src/writer/hlsl/generator_impl_loop_test.cc
+++ b/src/writer/hlsl/generator_impl_loop_test.cc
@@ -34,8 +34,8 @@
 using HlslGeneratorImplTest_Loop = TestHelper;
 
 TEST_F(HlslGeneratorImplTest_Loop, Emit_Loop) {
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::DiscardStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::DiscardStatement>());
 
   ast::LoopStatement l(std::move(body), {});
   gen.increment_indent();
@@ -48,11 +48,11 @@
 }
 
 TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopWithContinuing) {
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::DiscardStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::DiscardStatement>());
 
-  auto continuing = std::make_unique<ast::BlockStatement>();
-  continuing->append(std::make_unique<ast::ReturnStatement>());
+  auto continuing = create<ast::BlockStatement>();
+  continuing->append(create<ast::ReturnStatement>());
 
   ast::LoopStatement l(std::move(body), std::move(continuing));
   gen.increment_indent();
@@ -75,24 +75,24 @@
 TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopNestedWithContinuing) {
   ast::type::F32Type f32;
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::DiscardStatement>());
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::DiscardStatement>());
 
-  auto continuing = std::make_unique<ast::BlockStatement>();
-  continuing->append(std::make_unique<ast::ReturnStatement>());
+  auto continuing = create<ast::BlockStatement>();
+  continuing->append(create<ast::ReturnStatement>());
 
-  auto inner = std::make_unique<ast::LoopStatement>(std::move(body),
-                                                    std::move(continuing));
+  auto inner =
+      create<ast::LoopStatement>(std::move(body), std::move(continuing));
 
-  body = std::make_unique<ast::BlockStatement>();
+  body = create<ast::BlockStatement>();
   body->append(std::move(inner));
 
-  auto lhs = std::make_unique<ast::IdentifierExpression>("lhs");
-  auto rhs = std::make_unique<ast::IdentifierExpression>("rhs");
+  auto lhs = create<ast::IdentifierExpression>("lhs");
+  auto rhs = create<ast::IdentifierExpression>("rhs");
 
-  continuing = std::make_unique<ast::BlockStatement>();
-  continuing->append(std::make_unique<ast::AssignmentStatement>(
-      std::move(lhs), std::move(rhs)));
+  continuing = create<ast::BlockStatement>();
+  continuing->append(
+      create<ast::AssignmentStatement>(std::move(lhs), std::move(rhs)));
 
   ast::LoopStatement outer(std::move(body), std::move(continuing));
   gen.increment_indent();
@@ -146,23 +146,21 @@
 
   ast::type::F32Type f32;
 
-  auto var = std::make_unique<ast::Variable>(
-      "lhs", ast::StorageClass::kFunction, &f32);
-  var->set_constructor(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 2.4)));
+  auto var = create<ast::Variable>("lhs", ast::StorageClass::kFunction, &f32);
+  var->set_constructor(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 2.4)));
 
-  auto body = std::make_unique<ast::BlockStatement>();
-  body->append(std::make_unique<ast::VariableDeclStatement>(std::move(var)));
-  body->append(std::make_unique<ast::VariableDeclStatement>(
-      std::make_unique<ast::Variable>("other", ast::StorageClass::kFunction,
-                                      &f32)));
+  auto body = create<ast::BlockStatement>();
+  body->append(create<ast::VariableDeclStatement>(std::move(var)));
+  body->append(create<ast::VariableDeclStatement>(
+      create<ast::Variable>("other", ast::StorageClass::kFunction, &f32)));
 
-  auto lhs = std::make_unique<ast::IdentifierExpression>("lhs");
-  auto rhs = std::make_unique<ast::IdentifierExpression>("rhs");
+  auto lhs = create<ast::IdentifierExpression>("lhs");
+  auto rhs = create<ast::IdentifierExpression>("rhs");
 
-  auto continuing = std::make_unique<ast::BlockStatement>();
-  continuing->append(std::make_unique<ast::AssignmentStatement>(
-      std::move(lhs), std::move(rhs)));
+  auto continuing = create<ast::BlockStatement>();
+  continuing->append(
+      create<ast::AssignmentStatement>(std::move(lhs), std::move(rhs)));
 
   ast::LoopStatement outer(std::move(body), std::move(continuing));
   gen.increment_indent();
diff --git a/src/writer/hlsl/generator_impl_member_accessor_test.cc b/src/writer/hlsl/generator_impl_member_accessor_test.cc
index 57112e8..61f1df5 100644
--- a/src/writer/hlsl/generator_impl_member_accessor_test.cc
+++ b/src/writer/hlsl/generator_impl_member_accessor_test.cc
@@ -51,21 +51,19 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList deco;
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("mem", &f32, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("mem", &f32, std::move(deco)));
 
-  auto strct = std::make_unique<ast::Struct>();
+  auto strct = create<ast::Struct>();
   strct->set_members(std::move(members));
 
   ast::type::StructType s("Str", std::move(strct));
 
-  auto str_var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("str", ast::StorageClass::kPrivate, &s));
+  auto str_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("str", ast::StorageClass::kPrivate, &s));
 
-  auto str = std::make_unique<ast::IdentifierExpression>("str");
-  auto mem = std::make_unique<ast::IdentifierExpression>("mem");
+  auto str = create<ast::IdentifierExpression>("str");
+  auto mem = create<ast::IdentifierExpression>("mem");
 
   ast::MemberAccessorExpression expr(std::move(str), std::move(mem));
 
@@ -93,29 +91,23 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &i32, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &i32, std::move(a_deco)));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(4, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(4, Source{}));
+  members.push_back(create<ast::StructMember>("b", &f32, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &s));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("data", ast::StorageClass::kStorageBuffer, &s));
 
-  ast::MemberAccessorExpression expr(
-      std::make_unique<ast::IdentifierExpression>("data"),
-      std::make_unique<ast::IdentifierExpression>("b"));
+  ast::MemberAccessorExpression expr(create<ast::IdentifierExpression>("data"),
+                                     create<ast::IdentifierExpression>("b"));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -143,29 +135,23 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &i32, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &i32, std::move(a_deco)));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(4, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(4, Source{}));
+  members.push_back(create<ast::StructMember>("b", &f32, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &s));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("data", ast::StorageClass::kStorageBuffer, &s));
 
-  ast::MemberAccessorExpression expr(
-      std::make_unique<ast::IdentifierExpression>("data"),
-      std::make_unique<ast::IdentifierExpression>("a"));
+  ast::MemberAccessorExpression expr(create<ast::IdentifierExpression>("data"),
+                                     create<ast::IdentifierExpression>("a"));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -196,32 +182,27 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("z", &i32, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("z", &i32, std::move(a_deco)));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(4, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &mat, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(4, Source{}));
+  members.push_back(create<ast::StructMember>("a", &mat, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
 
-  auto b_var =
-      std::make_unique<ast::Variable>("b", ast::StorageClass::kPrivate, &mat);
+  auto b_var = create<ast::Variable>("b", ast::StorageClass::kPrivate, &mat);
 
-  auto coord_var = std::make_unique<ast::Variable>(
-      "data", ast::StorageClass::kStorageBuffer, &s);
+  auto coord_var =
+      create<ast::Variable>("data", ast::StorageClass::kStorageBuffer, &s);
 
-  auto lhs = std::make_unique<ast::MemberAccessorExpression>(
-      std::make_unique<ast::IdentifierExpression>("data"),
-      std::make_unique<ast::IdentifierExpression>("a"));
-  auto rhs = std::make_unique<ast::IdentifierExpression>("b");
+  auto lhs = create<ast::MemberAccessorExpression>(
+      create<ast::IdentifierExpression>("data"),
+      create<ast::IdentifierExpression>("a"));
+  auto rhs = create<ast::IdentifierExpression>("b");
 
   ast::AssignmentStatement assign(std::move(lhs), std::move(rhs));
 
@@ -261,31 +242,26 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("z", &i32, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("z", &i32, std::move(a_deco)));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(4, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &mat, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(4, Source{}));
+  members.push_back(create<ast::StructMember>("a", &mat, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &s));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("data", ast::StorageClass::kStorageBuffer, &s));
 
-  auto lhs = std::make_unique<ast::MemberAccessorExpression>(
-      std::make_unique<ast::IdentifierExpression>("data"),
-      std::make_unique<ast::IdentifierExpression>("a"));
-  auto rhs = std::make_unique<ast::TypeConstructorExpression>(
-      &mat, ast::ExpressionList{});
+  auto lhs = create<ast::MemberAccessorExpression>(
+      create<ast::IdentifierExpression>("data"),
+      create<ast::IdentifierExpression>("a"));
+  auto rhs =
+      create<ast::TypeConstructorExpression>(&mat, ast::ExpressionList{});
 
   ast::AssignmentStatement assign(std::move(lhs), std::move(rhs));
 
@@ -322,29 +298,23 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("z", &i32, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("z", &i32, std::move(a_deco)));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(4, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &mat, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(4, Source{}));
+  members.push_back(create<ast::StructMember>("a", &mat, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &s));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("data", ast::StorageClass::kStorageBuffer, &s));
 
-  ast::MemberAccessorExpression expr(
-      std::make_unique<ast::IdentifierExpression>("data"),
-      std::make_unique<ast::IdentifierExpression>("a"));
+  ast::MemberAccessorExpression expr(create<ast::IdentifierExpression>("data"),
+                                     create<ast::IdentifierExpression>("a"));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -379,29 +349,23 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("z", &i32, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("z", &i32, std::move(a_deco)));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(4, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &mat, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(4, Source{}));
+  members.push_back(create<ast::StructMember>("a", &mat, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &s));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("data", ast::StorageClass::kStorageBuffer, &s));
 
-  ast::MemberAccessorExpression expr(
-      std::make_unique<ast::IdentifierExpression>("data"),
-      std::make_unique<ast::IdentifierExpression>("a"));
+  ast::MemberAccessorExpression expr(create<ast::IdentifierExpression>("data"),
+                                     create<ast::IdentifierExpression>("a"));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -433,23 +397,19 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList deco;
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &mat, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &mat, std::move(deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &s));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("data", ast::StorageClass::kStorageBuffer, &s));
 
-  ast::MemberAccessorExpression expr(
-      std::make_unique<ast::IdentifierExpression>("data"),
-      std::make_unique<ast::IdentifierExpression>("a"));
+  ast::MemberAccessorExpression expr(create<ast::IdentifierExpression>("data"),
+                                     create<ast::IdentifierExpression>("a"));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -480,35 +440,30 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("z", &i32, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("z", &i32, std::move(a_deco)));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(16, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &mat, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(16, Source{}));
+  members.push_back(create<ast::StructMember>("a", &mat, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &s));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("data", ast::StorageClass::kStorageBuffer, &s));
 
   ast::ArrayAccessorExpression expr(
-      std::make_unique<ast::ArrayAccessorExpression>(
-          std::make_unique<ast::MemberAccessorExpression>(
-              std::make_unique<ast::IdentifierExpression>("data"),
-              std::make_unique<ast::IdentifierExpression>("a")),
-          std::make_unique<ast::ScalarConstructorExpression>(
-              std::make_unique<ast::SintLiteral>(&i32, 2))),
-      std::make_unique<ast::ScalarConstructorExpression>(
-          std::make_unique<ast::SintLiteral>(&i32, 1)));
+      create<ast::ArrayAccessorExpression>(
+          create<ast::MemberAccessorExpression>(
+              create<ast::IdentifierExpression>("data"),
+              create<ast::IdentifierExpression>("a")),
+          create<ast::ScalarConstructorExpression>(
+              create<ast::SintLiteral>(&i32, 2))),
+      create<ast::ScalarConstructorExpression>(
+          create<ast::SintLiteral>(&i32, 1)));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -534,31 +489,28 @@
   ast::type::I32Type i32;
   ast::type::ArrayType ary(&i32, 5);
   ast::ArrayDecorationList decos;
-  decos.push_back(std::make_unique<ast::StrideDecoration>(4, Source{}));
+  decos.push_back(create<ast::StrideDecoration>(4, Source{}));
   ary.set_decorations(std::move(decos));
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &ary, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &ary, std::move(a_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &s));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("data", ast::StorageClass::kStorageBuffer, &s));
 
   ast::ArrayAccessorExpression expr(
-      std::make_unique<ast::MemberAccessorExpression>(
-          std::make_unique<ast::IdentifierExpression>("data"),
-          std::make_unique<ast::IdentifierExpression>("a")),
-      std::make_unique<ast::ScalarConstructorExpression>(
-          std::make_unique<ast::SintLiteral>(&i32, 2)));
+      create<ast::MemberAccessorExpression>(
+          create<ast::IdentifierExpression>("data"),
+          create<ast::IdentifierExpression>("a")),
+      create<ast::ScalarConstructorExpression>(
+          create<ast::SintLiteral>(&i32, 2)));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -584,39 +536,36 @@
   ast::type::I32Type i32;
   ast::type::ArrayType ary(&i32, 5);
   ast::ArrayDecorationList decos;
-  decos.push_back(std::make_unique<ast::StrideDecoration>(4, Source{}));
+  decos.push_back(create<ast::StrideDecoration>(4, Source{}));
   ary.set_decorations(std::move(decos));
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &ary, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &ary, std::move(a_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &s));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("data", ast::StorageClass::kStorageBuffer, &s));
 
   ast::ArrayAccessorExpression expr(
-      std::make_unique<ast::MemberAccessorExpression>(
-          std::make_unique<ast::IdentifierExpression>("data"),
-          std::make_unique<ast::IdentifierExpression>("a")),
-      std::make_unique<ast::BinaryExpression>(
+      create<ast::MemberAccessorExpression>(
+          create<ast::IdentifierExpression>("data"),
+          create<ast::IdentifierExpression>("a")),
+      create<ast::BinaryExpression>(
           ast::BinaryOp::kSubtract,
-          std::make_unique<ast::BinaryExpression>(
+          create<ast::BinaryExpression>(
               ast::BinaryOp::kAdd,
-              std::make_unique<ast::ScalarConstructorExpression>(
-                  std::make_unique<ast::SintLiteral>(&i32, 2)),
-              std::make_unique<ast::ScalarConstructorExpression>(
-                  std::make_unique<ast::SintLiteral>(&i32, 4))),
-          std::make_unique<ast::ScalarConstructorExpression>(
-              std::make_unique<ast::SintLiteral>(&i32, 3))));
+              create<ast::ScalarConstructorExpression>(
+                  create<ast::SintLiteral>(&i32, 2)),
+              create<ast::ScalarConstructorExpression>(
+                  create<ast::SintLiteral>(&i32, 4))),
+          create<ast::ScalarConstructorExpression>(
+              create<ast::SintLiteral>(&i32, 3))));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -645,25 +594,20 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &i32, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &i32, std::move(a_deco)));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(4, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(4, Source{}));
+  members.push_back(create<ast::StructMember>("b", &f32, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &s));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("data", ast::StorageClass::kStorageBuffer, &s));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -671,11 +615,11 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  auto lhs = std::make_unique<ast::MemberAccessorExpression>(
-      std::make_unique<ast::IdentifierExpression>("data"),
-      std::make_unique<ast::IdentifierExpression>("b"));
-  auto rhs = std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 2.0f));
+  auto lhs = create<ast::MemberAccessorExpression>(
+      create<ast::IdentifierExpression>("data"),
+      create<ast::IdentifierExpression>("b"));
+  auto rhs = create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 2.0f));
   ast::AssignmentStatement assign(std::move(lhs), std::move(rhs));
 
   ASSERT_TRUE(td.DetermineResultType(&assign));
@@ -698,24 +642,21 @@
   ast::type::I32Type i32;
   ast::type::ArrayType ary(&i32, 5);
   ast::ArrayDecorationList decos;
-  decos.push_back(std::make_unique<ast::StrideDecoration>(4, Source{}));
+  decos.push_back(create<ast::StrideDecoration>(4, Source{}));
   ary.set_decorations(std::move(decos));
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &ary, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &ary, std::move(a_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &s));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("data", ast::StorageClass::kStorageBuffer, &s));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -723,14 +664,14 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  auto lhs = std::make_unique<ast::ArrayAccessorExpression>(
-      std::make_unique<ast::MemberAccessorExpression>(
-          std::make_unique<ast::IdentifierExpression>("data"),
-          std::make_unique<ast::IdentifierExpression>("a")),
-      std::make_unique<ast::ScalarConstructorExpression>(
-          std::make_unique<ast::SintLiteral>(&i32, 2)));
-  auto rhs = std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::SintLiteral>(&i32, 2));
+  auto lhs = create<ast::ArrayAccessorExpression>(
+      create<ast::MemberAccessorExpression>(
+          create<ast::IdentifierExpression>("data"),
+          create<ast::IdentifierExpression>("a")),
+      create<ast::ScalarConstructorExpression>(
+          create<ast::SintLiteral>(&i32, 2)));
+  auto rhs = create<ast::ScalarConstructorExpression>(
+      create<ast::SintLiteral>(&i32, 2));
   ast::AssignmentStatement assign(std::move(lhs), std::move(rhs));
 
   ASSERT_TRUE(td.DetermineResultType(&assign)) << td.error();
@@ -755,25 +696,20 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &i32, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &i32, std::move(a_deco)));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(4, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(4, Source{}));
+  members.push_back(create<ast::StructMember>("b", &f32, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &s));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("data", ast::StorageClass::kStorageBuffer, &s));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -781,11 +717,11 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  auto lhs = std::make_unique<ast::MemberAccessorExpression>(
-      std::make_unique<ast::IdentifierExpression>("data"),
-      std::make_unique<ast::IdentifierExpression>("a"));
-  auto rhs = std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::SintLiteral>(&i32, 2));
+  auto lhs = create<ast::MemberAccessorExpression>(
+      create<ast::IdentifierExpression>("data"),
+      create<ast::IdentifierExpression>("a"));
+  auto rhs = create<ast::ScalarConstructorExpression>(
+      create<ast::SintLiteral>(&i32, 2));
   ast::AssignmentStatement assign(std::move(lhs), std::move(rhs));
 
   ASSERT_TRUE(td.DetermineResultType(&assign));
@@ -812,25 +748,20 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &ivec3, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &ivec3, std::move(a_deco)));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(16, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &fvec3, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(16, Source{}));
+  members.push_back(create<ast::StructMember>("b", &fvec3, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &s));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("data", ast::StorageClass::kStorageBuffer, &s));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -838,9 +769,8 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  ast::MemberAccessorExpression expr(
-      std::make_unique<ast::IdentifierExpression>("data"),
-      std::make_unique<ast::IdentifierExpression>("b"));
+  ast::MemberAccessorExpression expr(create<ast::IdentifierExpression>("data"),
+                                     create<ast::IdentifierExpression>("b"));
 
   ASSERT_TRUE(td.DetermineResultType(&expr));
   ASSERT_TRUE(gen.EmitExpression(pre, out, &expr)) << gen.error();
@@ -865,25 +795,20 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList a_deco;
-  a_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &ivec3, std::move(a_deco)));
+  a_deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &ivec3, std::move(a_deco)));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(16, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &fvec3, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(16, Source{}));
+  members.push_back(create<ast::StructMember>("b", &fvec3, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("Data", std::move(str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &s));
+  auto coord_var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("data", ast::StorageClass::kStorageBuffer, &s));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -891,22 +816,18 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  auto lit1 = std::make_unique<ast::FloatLiteral>(&f32, 1.f);
-  auto lit2 = std::make_unique<ast::FloatLiteral>(&f32, 2.f);
-  auto lit3 = std::make_unique<ast::FloatLiteral>(&f32, 3.f);
+  auto lit1 = create<ast::FloatLiteral>(&f32, 1.f);
+  auto lit2 = create<ast::FloatLiteral>(&f32, 2.f);
+  auto lit3 = create<ast::FloatLiteral>(&f32, 3.f);
   ast::ExpressionList values;
-  values.push_back(
-      std::make_unique<ast::ScalarConstructorExpression>(std::move(lit1)));
-  values.push_back(
-      std::make_unique<ast::ScalarConstructorExpression>(std::move(lit2)));
-  values.push_back(
-      std::make_unique<ast::ScalarConstructorExpression>(std::move(lit3)));
+  values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit1)));
+  values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit2)));
+  values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit3)));
 
-  auto lhs = std::make_unique<ast::MemberAccessorExpression>(
-      std::make_unique<ast::IdentifierExpression>("data"),
-      std::make_unique<ast::IdentifierExpression>("b"));
-  auto rhs = std::make_unique<ast::TypeConstructorExpression>(
-      &fvec3, std::move(values));
+  auto lhs = create<ast::MemberAccessorExpression>(
+      create<ast::IdentifierExpression>("data"),
+      create<ast::IdentifierExpression>("b"));
+  auto rhs = create<ast::TypeConstructorExpression>(&fvec3, std::move(values));
 
   ast::AssignmentStatement assign(std::move(lhs), std::move(rhs));
 
@@ -940,39 +861,32 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList deco;
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &ivec3, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &ivec3, std::move(deco)));
 
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(16, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &fvec3, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(16, Source{}));
+  members.push_back(create<ast::StructMember>("b", &fvec3, std::move(deco)));
 
-  auto data_str = std::make_unique<ast::Struct>();
+  auto data_str = create<ast::Struct>();
   data_str->set_members(std::move(members));
 
   ast::type::StructType data("Data", std::move(data_str));
 
   ast::type::ArrayType ary(&data, 4);
   ast::ArrayDecorationList decos;
-  decos.push_back(std::make_unique<ast::StrideDecoration>(32, Source{}));
+  decos.push_back(create<ast::StrideDecoration>(32, Source{}));
   ary.set_decorations(std::move(decos));
 
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("c", &ary, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("c", &ary, std::move(deco)));
 
-  auto pre_str = std::make_unique<ast::Struct>();
+  auto pre_str = create<ast::Struct>();
   pre_str->set_members(std::move(members));
 
   ast::type::StructType pre_struct("Pre", std::move(pre_str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &pre_struct));
+  auto coord_var = create<ast::DecoratedVariable>(create<ast::Variable>(
+      "data", ast::StorageClass::kStorageBuffer, &pre_struct));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -981,13 +895,13 @@
   ASSERT_TRUE(td.Determine()) << td.error();
 
   ast::MemberAccessorExpression expr(
-      std::make_unique<ast::ArrayAccessorExpression>(
-          std::make_unique<ast::MemberAccessorExpression>(
-              std::make_unique<ast::IdentifierExpression>("data"),
-              std::make_unique<ast::IdentifierExpression>("c")),
-          std::make_unique<ast::ScalarConstructorExpression>(
-              std::make_unique<ast::SintLiteral>(&i32, 2))),
-      std::make_unique<ast::IdentifierExpression>("b"));
+      create<ast::ArrayAccessorExpression>(
+          create<ast::MemberAccessorExpression>(
+              create<ast::IdentifierExpression>("data"),
+              create<ast::IdentifierExpression>("c")),
+          create<ast::ScalarConstructorExpression>(
+              create<ast::SintLiteral>(&i32, 2))),
+      create<ast::IdentifierExpression>("b"));
 
   ASSERT_TRUE(td.DetermineResultType(&expr));
   ASSERT_TRUE(gen.EmitExpression(pre, out, &expr)) << gen.error();
@@ -1016,39 +930,32 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList deco;
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &ivec3, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &ivec3, std::move(deco)));
 
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(16, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &fvec3, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(16, Source{}));
+  members.push_back(create<ast::StructMember>("b", &fvec3, std::move(deco)));
 
-  auto data_str = std::make_unique<ast::Struct>();
+  auto data_str = create<ast::Struct>();
   data_str->set_members(std::move(members));
 
   ast::type::StructType data("Data", std::move(data_str));
 
   ast::type::ArrayType ary(&data, 4);
   ast::ArrayDecorationList decos;
-  decos.push_back(std::make_unique<ast::StrideDecoration>(32, Source{}));
+  decos.push_back(create<ast::StrideDecoration>(32, Source{}));
   ary.set_decorations(std::move(decos));
 
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("c", &ary, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("c", &ary, std::move(deco)));
 
-  auto pre_str = std::make_unique<ast::Struct>();
+  auto pre_str = create<ast::Struct>();
   pre_str->set_members(std::move(members));
 
   ast::type::StructType pre_struct("Pre", std::move(pre_str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &pre_struct));
+  auto coord_var = create<ast::DecoratedVariable>(create<ast::Variable>(
+      "data", ast::StorageClass::kStorageBuffer, &pre_struct));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -1057,15 +964,15 @@
   ASSERT_TRUE(td.Determine()) << td.error();
 
   ast::MemberAccessorExpression expr(
-      std::make_unique<ast::MemberAccessorExpression>(
-          std::make_unique<ast::ArrayAccessorExpression>(
-              std::make_unique<ast::MemberAccessorExpression>(
-                  std::make_unique<ast::IdentifierExpression>("data"),
-                  std::make_unique<ast::IdentifierExpression>("c")),
-              std::make_unique<ast::ScalarConstructorExpression>(
-                  std::make_unique<ast::SintLiteral>(&i32, 2))),
-          std::make_unique<ast::IdentifierExpression>("b")),
-      std::make_unique<ast::IdentifierExpression>("xy"));
+      create<ast::MemberAccessorExpression>(
+          create<ast::ArrayAccessorExpression>(
+              create<ast::MemberAccessorExpression>(
+                  create<ast::IdentifierExpression>("data"),
+                  create<ast::IdentifierExpression>("c")),
+              create<ast::ScalarConstructorExpression>(
+                  create<ast::SintLiteral>(&i32, 2))),
+          create<ast::IdentifierExpression>("b")),
+      create<ast::IdentifierExpression>("xy"));
 
   ASSERT_TRUE(td.DetermineResultType(&expr));
   ASSERT_TRUE(gen.EmitExpression(pre, out, &expr)) << gen.error();
@@ -1095,39 +1002,32 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList deco;
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &ivec3, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &ivec3, std::move(deco)));
 
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(16, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &fvec3, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(16, Source{}));
+  members.push_back(create<ast::StructMember>("b", &fvec3, std::move(deco)));
 
-  auto data_str = std::make_unique<ast::Struct>();
+  auto data_str = create<ast::Struct>();
   data_str->set_members(std::move(members));
 
   ast::type::StructType data("Data", std::move(data_str));
 
   ast::type::ArrayType ary(&data, 4);
   ast::ArrayDecorationList decos;
-  decos.push_back(std::make_unique<ast::StrideDecoration>(32, Source{}));
+  decos.push_back(create<ast::StrideDecoration>(32, Source{}));
   ary.set_decorations(std::move(decos));
 
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("c", &ary, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("c", &ary, std::move(deco)));
 
-  auto pre_str = std::make_unique<ast::Struct>();
+  auto pre_str = create<ast::Struct>();
   pre_str->set_members(std::move(members));
 
   ast::type::StructType pre_struct("Pre", std::move(pre_str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &pre_struct));
+  auto coord_var = create<ast::DecoratedVariable>(create<ast::Variable>(
+      "data", ast::StorageClass::kStorageBuffer, &pre_struct));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -1136,15 +1036,15 @@
   ASSERT_TRUE(td.Determine()) << td.error();
 
   ast::MemberAccessorExpression expr(
-      std::make_unique<ast::MemberAccessorExpression>(
-          std::make_unique<ast::ArrayAccessorExpression>(
-              std::make_unique<ast::MemberAccessorExpression>(
-                  std::make_unique<ast::IdentifierExpression>("data"),
-                  std::make_unique<ast::IdentifierExpression>("c")),
-              std::make_unique<ast::ScalarConstructorExpression>(
-                  std::make_unique<ast::SintLiteral>(&i32, 2))),
-          std::make_unique<ast::IdentifierExpression>("b")),
-      std::make_unique<ast::IdentifierExpression>("g"));
+      create<ast::MemberAccessorExpression>(
+          create<ast::ArrayAccessorExpression>(
+              create<ast::MemberAccessorExpression>(
+                  create<ast::IdentifierExpression>("data"),
+                  create<ast::IdentifierExpression>("c")),
+              create<ast::ScalarConstructorExpression>(
+                  create<ast::SintLiteral>(&i32, 2))),
+          create<ast::IdentifierExpression>("b")),
+      create<ast::IdentifierExpression>("g"));
 
   ASSERT_TRUE(td.DetermineResultType(&expr));
   ASSERT_TRUE(gen.EmitExpression(pre, out, &expr)) << gen.error();
@@ -1173,39 +1073,32 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList deco;
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &ivec3, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &ivec3, std::move(deco)));
 
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(16, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &fvec3, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(16, Source{}));
+  members.push_back(create<ast::StructMember>("b", &fvec3, std::move(deco)));
 
-  auto data_str = std::make_unique<ast::Struct>();
+  auto data_str = create<ast::Struct>();
   data_str->set_members(std::move(members));
 
   ast::type::StructType data("Data", std::move(data_str));
 
   ast::type::ArrayType ary(&data, 4);
   ast::ArrayDecorationList decos;
-  decos.push_back(std::make_unique<ast::StrideDecoration>(32, Source{}));
+  decos.push_back(create<ast::StrideDecoration>(32, Source{}));
   ary.set_decorations(std::move(decos));
 
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("c", &ary, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("c", &ary, std::move(deco)));
 
-  auto pre_str = std::make_unique<ast::Struct>();
+  auto pre_str = create<ast::Struct>();
   pre_str->set_members(std::move(members));
 
   ast::type::StructType pre_struct("Pre", std::move(pre_str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &pre_struct));
+  auto coord_var = create<ast::DecoratedVariable>(create<ast::Variable>(
+      "data", ast::StorageClass::kStorageBuffer, &pre_struct));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -1214,16 +1107,16 @@
   ASSERT_TRUE(td.Determine()) << td.error();
 
   ast::ArrayAccessorExpression expr(
-      std::make_unique<ast::MemberAccessorExpression>(
-          std::make_unique<ast::ArrayAccessorExpression>(
-              std::make_unique<ast::MemberAccessorExpression>(
-                  std::make_unique<ast::IdentifierExpression>("data"),
-                  std::make_unique<ast::IdentifierExpression>("c")),
-              std::make_unique<ast::ScalarConstructorExpression>(
-                  std::make_unique<ast::SintLiteral>(&i32, 2))),
-          std::make_unique<ast::IdentifierExpression>("b")),
-      std::make_unique<ast::ScalarConstructorExpression>(
-          std::make_unique<ast::SintLiteral>(&i32, 1)));
+      create<ast::MemberAccessorExpression>(
+          create<ast::ArrayAccessorExpression>(
+              create<ast::MemberAccessorExpression>(
+                  create<ast::IdentifierExpression>("data"),
+                  create<ast::IdentifierExpression>("c")),
+              create<ast::ScalarConstructorExpression>(
+                  create<ast::SintLiteral>(&i32, 2))),
+          create<ast::IdentifierExpression>("b")),
+      create<ast::ScalarConstructorExpression>(
+          create<ast::SintLiteral>(&i32, 1)));
 
   ASSERT_TRUE(td.DetermineResultType(&expr));
   ASSERT_TRUE(gen.EmitExpression(pre, out, &expr)) << gen.error();
@@ -1252,39 +1145,32 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList deco;
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &ivec3, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &ivec3, std::move(deco)));
 
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(16, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &fvec3, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(16, Source{}));
+  members.push_back(create<ast::StructMember>("b", &fvec3, std::move(deco)));
 
-  auto data_str = std::make_unique<ast::Struct>();
+  auto data_str = create<ast::Struct>();
   data_str->set_members(std::move(members));
 
   ast::type::StructType data("Data", std::move(data_str));
 
   ast::type::ArrayType ary(&data, 4);
   ast::ArrayDecorationList decos;
-  decos.push_back(std::make_unique<ast::StrideDecoration>(32, Source{}));
+  decos.push_back(create<ast::StrideDecoration>(32, Source{}));
   ary.set_decorations(std::move(decos));
 
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("c", &ary, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("c", &ary, std::move(deco)));
 
-  auto pre_str = std::make_unique<ast::Struct>();
+  auto pre_str = create<ast::Struct>();
   pre_str->set_members(std::move(members));
 
   ast::type::StructType pre_struct("Pre", std::move(pre_str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &pre_struct));
+  auto coord_var = create<ast::DecoratedVariable>(create<ast::Variable>(
+      "data", ast::StorageClass::kStorageBuffer, &pre_struct));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -1292,28 +1178,24 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  auto lhs = std::make_unique<ast::MemberAccessorExpression>(
-      std::make_unique<ast::ArrayAccessorExpression>(
-          std::make_unique<ast::MemberAccessorExpression>(
-              std::make_unique<ast::IdentifierExpression>("data"),
-              std::make_unique<ast::IdentifierExpression>("c")),
-          std::make_unique<ast::ScalarConstructorExpression>(
-              std::make_unique<ast::SintLiteral>(&i32, 2))),
-      std::make_unique<ast::IdentifierExpression>("b"));
+  auto lhs = create<ast::MemberAccessorExpression>(
+      create<ast::ArrayAccessorExpression>(
+          create<ast::MemberAccessorExpression>(
+              create<ast::IdentifierExpression>("data"),
+              create<ast::IdentifierExpression>("c")),
+          create<ast::ScalarConstructorExpression>(
+              create<ast::SintLiteral>(&i32, 2))),
+      create<ast::IdentifierExpression>("b"));
 
-  auto lit1 = std::make_unique<ast::FloatLiteral>(&f32, 1.f);
-  auto lit2 = std::make_unique<ast::FloatLiteral>(&f32, 2.f);
-  auto lit3 = std::make_unique<ast::FloatLiteral>(&f32, 3.f);
+  auto lit1 = create<ast::FloatLiteral>(&f32, 1.f);
+  auto lit2 = create<ast::FloatLiteral>(&f32, 2.f);
+  auto lit3 = create<ast::FloatLiteral>(&f32, 3.f);
   ast::ExpressionList values;
-  values.push_back(
-      std::make_unique<ast::ScalarConstructorExpression>(std::move(lit1)));
-  values.push_back(
-      std::make_unique<ast::ScalarConstructorExpression>(std::move(lit2)));
-  values.push_back(
-      std::make_unique<ast::ScalarConstructorExpression>(std::move(lit3)));
+  values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit1)));
+  values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit2)));
+  values.push_back(create<ast::ScalarConstructorExpression>(std::move(lit3)));
 
-  auto rhs = std::make_unique<ast::TypeConstructorExpression>(
-      &fvec3, std::move(values));
+  auto rhs = create<ast::TypeConstructorExpression>(&fvec3, std::move(values));
 
   ast::AssignmentStatement assign(std::move(lhs), std::move(rhs));
 
@@ -1347,39 +1229,32 @@
 
   ast::StructMemberList members;
   ast::StructMemberDecorationList deco;
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &ivec3, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("a", &ivec3, std::move(deco)));
 
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(16, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &fvec3, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(16, Source{}));
+  members.push_back(create<ast::StructMember>("b", &fvec3, std::move(deco)));
 
-  auto data_str = std::make_unique<ast::Struct>();
+  auto data_str = create<ast::Struct>();
   data_str->set_members(std::move(members));
 
   ast::type::StructType data("Data", std::move(data_str));
 
   ast::type::ArrayType ary(&data, 4);
   ast::ArrayDecorationList decos;
-  decos.push_back(std::make_unique<ast::StrideDecoration>(32, Source{}));
+  decos.push_back(create<ast::StrideDecoration>(32, Source{}));
   ary.set_decorations(std::move(decos));
 
-  deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(0, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("c", &ary, std::move(deco)));
+  deco.push_back(create<ast::StructMemberOffsetDecoration>(0, Source{}));
+  members.push_back(create<ast::StructMember>("c", &ary, std::move(deco)));
 
-  auto pre_str = std::make_unique<ast::Struct>();
+  auto pre_str = create<ast::Struct>();
   pre_str->set_members(std::move(members));
 
   ast::type::StructType pre_struct("Pre", std::move(pre_str));
 
-  auto coord_var =
-      std::make_unique<ast::DecoratedVariable>(std::make_unique<ast::Variable>(
-          "data", ast::StorageClass::kStorageBuffer, &pre_struct));
+  auto coord_var = create<ast::DecoratedVariable>(create<ast::Variable>(
+      "data", ast::StorageClass::kStorageBuffer, &pre_struct));
 
   td.RegisterVariableForTesting(coord_var.get());
   gen.register_global(coord_var.get());
@@ -1387,19 +1262,19 @@
 
   ASSERT_TRUE(td.Determine()) << td.error();
 
-  auto lhs = std::make_unique<ast::MemberAccessorExpression>(
-      std::make_unique<ast::MemberAccessorExpression>(
-          std::make_unique<ast::ArrayAccessorExpression>(
-              std::make_unique<ast::MemberAccessorExpression>(
-                  std::make_unique<ast::IdentifierExpression>("data"),
-                  std::make_unique<ast::IdentifierExpression>("c")),
-              std::make_unique<ast::ScalarConstructorExpression>(
-                  std::make_unique<ast::SintLiteral>(&i32, 2))),
-          std::make_unique<ast::IdentifierExpression>("b")),
-      std::make_unique<ast::IdentifierExpression>("y"));
+  auto lhs = create<ast::MemberAccessorExpression>(
+      create<ast::MemberAccessorExpression>(
+          create<ast::ArrayAccessorExpression>(
+              create<ast::MemberAccessorExpression>(
+                  create<ast::IdentifierExpression>("data"),
+                  create<ast::IdentifierExpression>("c")),
+              create<ast::ScalarConstructorExpression>(
+                  create<ast::SintLiteral>(&i32, 2))),
+          create<ast::IdentifierExpression>("b")),
+      create<ast::IdentifierExpression>("y"));
 
-  auto rhs = std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&i32, 1.f));
+  auto rhs = create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&i32, 1.f));
 
   ast::AssignmentStatement assign(std::move(lhs), std::move(rhs));
 
diff --git a/src/writer/hlsl/generator_impl_module_constant_test.cc b/src/writer/hlsl/generator_impl_module_constant_test.cc
index 93dd49c..f4e2e43 100644
--- a/src/writer/hlsl/generator_impl_module_constant_test.cc
+++ b/src/writer/hlsl/generator_impl_module_constant_test.cc
@@ -38,18 +38,17 @@
   ast::type::ArrayType ary(&f32, 3);
 
   ast::ExpressionList exprs;
-  exprs.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 1.0f)));
-  exprs.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 2.0f)));
-  exprs.push_back(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 3.0f)));
+  exprs.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 1.0f)));
+  exprs.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 2.0f)));
+  exprs.push_back(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 3.0f)));
 
-  auto var =
-      std::make_unique<ast::Variable>("pos", ast::StorageClass::kNone, &ary);
+  auto var = create<ast::Variable>("pos", ast::StorageClass::kNone, &ary);
   var->set_is_const(true);
   var->set_constructor(
-      std::make_unique<ast::TypeConstructorExpression>(&ary, std::move(exprs)));
+      create<ast::TypeConstructorExpression>(&ary, std::move(exprs)));
 
   ASSERT_TRUE(gen.EmitProgramConstVariable(out, var.get())) << gen.error();
   EXPECT_EQ(
@@ -61,14 +60,14 @@
   ast::type::F32Type f32;
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::ConstantIdDecoration>(23, Source{}));
+  decos.push_back(create<ast::ConstantIdDecoration>(23, Source{}));
 
-  auto var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("pos", ast::StorageClass::kNone, &f32));
+  auto var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("pos", ast::StorageClass::kNone, &f32));
   var->set_decorations(std::move(decos));
   var->set_is_const(true);
-  var->set_constructor(std::make_unique<ast::ScalarConstructorExpression>(
-      std::make_unique<ast::FloatLiteral>(&f32, 3.0f)));
+  var->set_constructor(create<ast::ScalarConstructorExpression>(
+      create<ast::FloatLiteral>(&f32, 3.0f)));
 
   ASSERT_TRUE(gen.EmitProgramConstVariable(out, var.get())) << gen.error();
   EXPECT_EQ(result(), R"(#ifndef WGSL_SPEC_CONSTANT_23
@@ -83,10 +82,10 @@
   ast::type::F32Type f32;
 
   ast::VariableDecorationList decos;
-  decos.push_back(std::make_unique<ast::ConstantIdDecoration>(23, Source{}));
+  decos.push_back(create<ast::ConstantIdDecoration>(23, Source{}));
 
-  auto var = std::make_unique<ast::DecoratedVariable>(
-      std::make_unique<ast::Variable>("pos", ast::StorageClass::kNone, &f32));
+  auto var = create<ast::DecoratedVariable>(
+      create<ast::Variable>("pos", ast::StorageClass::kNone, &f32));
   var->set_decorations(std::move(decos));
   var->set_is_const(true);
 
diff --git a/src/writer/hlsl/generator_impl_return_test.cc b/src/writer/hlsl/generator_impl_return_test.cc
index ee90420..7488c3c 100644
--- a/src/writer/hlsl/generator_impl_return_test.cc
+++ b/src/writer/hlsl/generator_impl_return_test.cc
@@ -36,7 +36,7 @@
 }
 
 TEST_F(HlslGeneratorImplTest_Return, Emit_ReturnWithValue) {
-  auto expr = std::make_unique<ast::IdentifierExpression>("expr");
+  auto expr = create<ast::IdentifierExpression>("expr");
   ast::ReturnStatement r(std::move(expr));
   gen.increment_indent();
 
diff --git a/src/writer/hlsl/generator_impl_switch_test.cc b/src/writer/hlsl/generator_impl_switch_test.cc
index 3768c0d..005f3d3 100644
--- a/src/writer/hlsl/generator_impl_switch_test.cc
+++ b/src/writer/hlsl/generator_impl_switch_test.cc
@@ -31,26 +31,26 @@
 using HlslGeneratorImplTest_Switch = TestHelper;
 
 TEST_F(HlslGeneratorImplTest_Switch, Emit_Switch) {
-  auto def = std::make_unique<ast::CaseStatement>();
-  auto def_body = std::make_unique<ast::BlockStatement>();
-  def_body->append(std::make_unique<ast::BreakStatement>());
+  auto def = create<ast::CaseStatement>();
+  auto def_body = create<ast::BlockStatement>();
+  def_body->append(create<ast::BreakStatement>());
   def->set_body(std::move(def_body));
 
   ast::type::I32Type i32;
   ast::CaseSelectorList case_val;
-  case_val.push_back(std::make_unique<ast::SintLiteral>(&i32, 5));
+  case_val.push_back(create<ast::SintLiteral>(&i32, 5));
 
-  auto case_body = std::make_unique<ast::BlockStatement>();
-  case_body->append(std::make_unique<ast::BreakStatement>());
+  auto case_body = create<ast::BlockStatement>();
+  case_body->append(create<ast::BreakStatement>());
 
-  auto case_stmt = std::make_unique<ast::CaseStatement>(std::move(case_val),
-                                                        std::move(case_body));
+  auto case_stmt =
+      create<ast::CaseStatement>(std::move(case_val), std::move(case_body));
 
   ast::CaseStatementList body;
   body.push_back(std::move(case_stmt));
   body.push_back(std::move(def));
 
-  auto cond = std::make_unique<ast::IdentifierExpression>("cond");
+  auto cond = create<ast::IdentifierExpression>("cond");
   ast::SwitchStatement s(std::move(cond), std::move(body));
   gen.increment_indent();
 
diff --git a/src/writer/hlsl/generator_impl_test.cc b/src/writer/hlsl/generator_impl_test.cc
index 22a6613..a92a5ed 100644
--- a/src/writer/hlsl/generator_impl_test.cc
+++ b/src/writer/hlsl/generator_impl_test.cc
@@ -29,8 +29,7 @@
 
 TEST_F(HlslGeneratorImplTest, Generate) {
   ast::type::VoidType void_type;
-  auto func = std::make_unique<ast::Function>("my_func", ast::VariableList{},
-                                              &void_type);
+  auto func = create<ast::Function>("my_func", ast::VariableList{}, &void_type);
   mod.AddFunction(std::move(func));
 
   ASSERT_TRUE(gen.Generate(out)) << gen.error();
diff --git a/src/writer/hlsl/generator_impl_type_test.cc b/src/writer/hlsl/generator_impl_type_test.cc
index ecab2d4..2fec741 100644
--- a/src/writer/hlsl/generator_impl_type_test.cc
+++ b/src/writer/hlsl/generator_impl_type_test.cc
@@ -174,16 +174,14 @@
   ast::type::F32Type f32;
 
   ast::StructMemberList members;
-  members.push_back(std::make_unique<ast::StructMember>(
-      "a", &i32, ast::StructMemberDecorationList{}));
+  members.push_back(
+      create<ast::StructMember>("a", &i32, ast::StructMemberDecorationList{}));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(4, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(4, Source{}));
+  members.push_back(create<ast::StructMember>("b", &f32, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("S", std::move(str));
@@ -201,16 +199,14 @@
   ast::type::F32Type f32;
 
   ast::StructMemberList members;
-  members.push_back(std::make_unique<ast::StructMember>(
-      "a", &i32, ast::StructMemberDecorationList{}));
+  members.push_back(
+      create<ast::StructMember>("a", &i32, ast::StructMemberDecorationList{}));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(4, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(4, Source{}));
+  members.push_back(create<ast::StructMember>("b", &f32, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("S", std::move(str));
@@ -224,24 +220,18 @@
   ast::type::F32Type f32;
 
   ast::StructMemberDecorationList decos;
-  decos.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(4, Source{}));
+  decos.push_back(create<ast::StructMemberOffsetDecoration>(4, Source{}));
 
   ast::StructMemberList members;
-  members.push_back(
-      std::make_unique<ast::StructMember>("a", &i32, std::move(decos)));
+  members.push_back(create<ast::StructMember>("a", &i32, std::move(decos)));
 
-  decos.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(32, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &f32, std::move(decos)));
+  decos.push_back(create<ast::StructMemberOffsetDecoration>(32, Source{}));
+  members.push_back(create<ast::StructMember>("b", &f32, std::move(decos)));
 
-  decos.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(128, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("c", &f32, std::move(decos)));
+  decos.push_back(create<ast::StructMemberOffsetDecoration>(128, Source{}));
+  members.push_back(create<ast::StructMember>("c", &f32, std::move(decos)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("S", std::move(str));
@@ -262,14 +252,14 @@
   ast::type::F32Type f32;
 
   ast::StructMemberList members;
-  members.push_back(std::make_unique<ast::StructMember>(
+  members.push_back(create<ast::StructMember>(
       "double", &i32, ast::StructMemberDecorationList{}));
 
   ast::StructMemberDecorationList b_deco;
   members.push_back(
-      std::make_unique<ast::StructMember>("float", &f32, std::move(b_deco)));
+      create<ast::StructMember>("float", &f32, std::move(b_deco)));
 
-  auto str = std::make_unique<ast::Struct>();
+  auto str = create<ast::Struct>();
   str->set_members(std::move(members));
 
   ast::type::StructType s("S", std::move(str));
@@ -288,20 +278,17 @@
   ast::type::F32Type f32;
 
   ast::StructMemberList members;
-  members.push_back(std::make_unique<ast::StructMember>(
-      "a", &i32, ast::StructMemberDecorationList{}));
+  members.push_back(
+      create<ast::StructMember>("a", &i32, ast::StructMemberDecorationList{}));
 
   ast::StructMemberDecorationList b_deco;
-  b_deco.push_back(
-      std::make_unique<ast::StructMemberOffsetDecoration>(4, Source{}));
-  members.push_back(
-      std::make_unique<ast::StructMember>("b", &f32, std::move(b_deco)));
+  b_deco.push_back(create<ast::StructMemberOffsetDecoration>(4, Source{}));
+  members.push_back(create<ast::StructMember>("b", &f32, std::move(b_deco)));
 
   ast::StructDecorationList decos;
-  decos.push_back(std::make_unique<ast::StructBlockDecoration>(Source{}));
+  decos.push_back(create<ast::StructBlockDecoration>(Source{}));
 
-  auto str =
-      std::make_unique<ast::Struct>(std::move(decos), std::move(members));
+  auto str = create<ast::Struct>(std::move(decos), std::move(members));
 
   ast::type::StructType s("S", std::move(str));
 
diff --git a/src/writer/hlsl/generator_impl_unary_op_test.cc b/src/writer/hlsl/generator_impl_unary_op_test.cc
index 751e23f..8fbf826 100644
--- a/src/writer/hlsl/generator_impl_unary_op_test.cc
+++ b/src/writer/hlsl/generator_impl_unary_op_test.cc
@@ -37,7 +37,7 @@
 TEST_P(HlslUnaryOpTest, Emit) {
   auto params = GetParam();
 
-  auto expr = std::make_unique<ast::IdentifierExpression>("expr");
+  auto expr = create<ast::IdentifierExpression>("expr");
   ast::UnaryOpExpression op(params.op, std::move(expr));
 
   ASSERT_TRUE(gen.EmitExpression(pre, out, &op)) << gen.error();
diff --git a/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc b/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc
index 81df764..651efd4 100644
--- a/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc
+++ b/src/writer/hlsl/generator_impl_variable_decl_statement_test.cc
@@ -34,8 +34,7 @@
 
 TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement) {
   ast::type::F32Type f32;
-  auto var =
-      std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &f32);
+  auto var = create<ast::Variable>("a", ast::StorageClass::kNone, &f32);
 
   ast::VariableDeclStatement stmt(std::move(var));
   gen.increment_indent();
@@ -46,8 +45,7 @@
 
 TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const) {
   ast::type::F32Type f32;
-  auto var =
-      std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &f32);
+  auto var = create<ast::Variable>("a", ast::StorageClass::kNone, &f32);
   var->set_is_const(true);
 
   ast::VariableDeclStatement stmt(std::move(var));
@@ -61,8 +59,7 @@
   ast::type::F32Type f32;
   ast::type::ArrayType ary(&f32, 5);
 
-  auto var =
-      std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &ary);
+  auto var = create<ast::Variable>("a", ast::StorageClass::kNone, &ary);
 
   ast::VariableDeclStatement stmt(std::move(var));
   gen.increment_indent();
@@ -74,8 +71,7 @@
 TEST_F(HlslGeneratorImplTest_VariableDecl,
        Emit_VariableDeclStatement_Function) {
   ast::type::F32Type f32;
-  auto var =
-      std::make_unique<ast::Variable>("a", ast::StorageClass::kFunction, &f32);
+  auto var = create<ast::Variable>("a", ast::StorageClass::kFunction, &f32);
 
   ast::VariableDeclStatement stmt(std::move(var));
   gen.increment_indent();
@@ -86,8 +82,7 @@
 
 TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Private) {
   ast::type::F32Type f32;
-  auto var =
-      std::make_unique<ast::Variable>("a", ast::StorageClass::kPrivate, &f32);
+  auto var = create<ast::Variable>("a", ast::StorageClass::kPrivate, &f32);
 
   ast::VariableDeclStatement stmt(std::move(var));
   gen.increment_indent();
@@ -98,11 +93,10 @@
 
 TEST_F(HlslGeneratorImplTest_VariableDecl,
        Emit_VariableDeclStatement_Initializer_Private) {
-  auto ident = std::make_unique<ast::IdentifierExpression>("initializer");
+  auto ident = create<ast::IdentifierExpression>("initializer");
 
   ast::type::F32Type f32;
-  auto var =
-      std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &f32);
+  auto var = create<ast::Variable>("a", ast::StorageClass::kNone, &f32);
   var->set_constructor(std::move(ident));
 
   ast::VariableDeclStatement stmt(std::move(var));
@@ -118,10 +112,9 @@
 
   ast::ExpressionList values;
   auto zero_vec =
-      std::make_unique<ast::TypeConstructorExpression>(&vec, std::move(values));
+      create<ast::TypeConstructorExpression>(&vec, std::move(values));
 
-  auto var =
-      std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &vec);
+  auto var = create<ast::Variable>("a", ast::StorageClass::kNone, &vec);
   var->set_constructor(std::move(zero_vec));
 
   ast::VariableDeclStatement stmt(std::move(var));
@@ -137,10 +130,9 @@
 
   ast::ExpressionList values;
   auto zero_mat =
-      std::make_unique<ast::TypeConstructorExpression>(&mat, std::move(values));
+      create<ast::TypeConstructorExpression>(&mat, std::move(values));
 
-  auto var =
-      std::make_unique<ast::Variable>("a", ast::StorageClass::kNone, &mat);
+  auto var = create<ast::Variable>("a", ast::StorageClass::kNone, &mat);
   var->set_constructor(std::move(zero_mat));
 
   ast::VariableDeclStatement stmt(std::move(var));
diff --git a/src/writer/hlsl/test_helper.h b/src/writer/hlsl/test_helper.h
index d83cee1..121f497 100644
--- a/src/writer/hlsl/test_helper.h
+++ b/src/writer/hlsl/test_helper.h
@@ -15,8 +15,10 @@
 #ifndef SRC_WRITER_HLSL_TEST_HELPER_H_
 #define SRC_WRITER_HLSL_TEST_HELPER_H_
 
+#include <memory>
 #include <sstream>
 #include <string>
+#include <utility>
 
 #include "gtest/gtest.h"
 #include "src/ast/module.h"
@@ -29,8 +31,8 @@
 namespace hlsl {
 
 /// Helper class for testing
-template <typename T>
-class TestHelperBase : public T {
+template <typename BODY>
+class TestHelperBase : public BODY {
  public:
   TestHelperBase() : td(&ctx, &mod), gen(&ctx, &mod) {}
   ~TestHelperBase() = default;
@@ -41,6 +43,13 @@
   /// @returns the pre result string
   std::string pre_result() const { return pre.str(); }
 
+  /// @return a `std::unique_ptr` to a new `T` constructed with `args`
+  /// @param args the arguments to forward to the constructor for `T`
+  template <typename T, typename... ARGS>
+  std::unique_ptr<T> create(ARGS&&... args) {
+    return std::make_unique<T>(std::forward<ARGS>(args)...);
+  }
+
   /// The context
   Context ctx;
   /// The module