Start cleaning up tests (3/N)

Remove Source{} with ast::Builder::create<>
Use Builder helpers where possible

Change-Id: I7b3188fa8239bf11e88ff6b396a57c23d76a3152
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/35660
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index d59faf4..01684a9 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -750,6 +750,7 @@
 
 source_set("tint_unittests_core_src") {
   sources = [
+    "src/ast/access_decoration_test.cc",
     "src/ast/array_accessor_expression_test.cc",
     "src/ast/assignment_statement_test.cc",
     "src/ast/binary_expression_test.cc",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9a063af..1a7c6a4 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -387,6 +387,7 @@
 
 if(${TINT_BUILD_TESTS})
   set(TINT_TEST_SRCS
+    ast/access_decoration_test.cc
     ast/array_accessor_expression_test.cc
     ast/assignment_statement_test.cc
     ast/binding_decoration_test.cc
diff --git a/src/ast/access_decoration_test.cc b/src/ast/access_decoration_test.cc
index 36c030d..55295fc 100644
--- a/src/ast/access_decoration_test.cc
+++ b/src/ast/access_decoration_test.cc
@@ -25,20 +25,20 @@
 using AccessDecorationTest = TestHelper;
 
 TEST_F(AccessDecorationTest, Creation) {
-  AccessDecoration d{ast::AccessControl::kWriteOnly, Source{}};
-  EXPECT_EQ(ast::AccessControl::kWriteOnly, d.value());
+  auto* d = create<AccessDecoration>(ast::AccessControl::kWriteOnly);
+  EXPECT_EQ(ast::AccessControl::kWriteOnly, d->value());
 }
 
 TEST_F(AccessDecorationTest, Is) {
-  AccessDecoration d{ast::AccessControl::kReadWrite, Source{}};
-  EXPECT_FALSE(d.IsAccess());
+  auto* d = create<AccessDecoration>(ast::AccessControl::kReadWrite);
+  EXPECT_TRUE(d->Is<ast::AccessDecoration>());
 }
 
 TEST_F(AccessDecorationTest, ToStr) {
-  AccessDecoration d{ast::AccessControl::kReadOnly, Source{}};
+  auto* d = create<AccessDecoration>(ast::AccessControl::kReadOnly);
   std::ostringstream out;
-  d.to_str(out, 0);
-  EXPECT_EQ(out.str(), R"(AccessDecoration{read}
+  d->to_str(out, 0);
+  EXPECT_EQ(out.str(), R"(AccessDecoration{read_only}
 )");
 }
 
diff --git a/src/ast/array_accessor_expression_test.cc b/src/ast/array_accessor_expression_test.cc
index 1de4435..be29266 100644
--- a/src/ast/array_accessor_expression_test.cc
+++ b/src/ast/array_accessor_expression_test.cc
@@ -24,91 +24,76 @@
 using ArrayAccessorExpressionTest = TestHelper;
 
 TEST_F(ArrayAccessorExpressionTest, Create) {
-  auto* ary =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("ary"), "ary");
-  auto* idx =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("idx"), "idx");
+  auto* ary = Expr("ary");
+  auto* idx = Expr("idx");
 
-  ArrayAccessorExpression exp(Source{}, ary, idx);
-  ASSERT_EQ(exp.array(), ary);
-  ASSERT_EQ(exp.idx_expr(), idx);
+  auto* exp = create<ArrayAccessorExpression>(ary, idx);
+  ASSERT_EQ(exp->array(), ary);
+  ASSERT_EQ(exp->idx_expr(), idx);
 }
 
 TEST_F(ArrayAccessorExpressionTest, CreateWithSource) {
-  auto* ary =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("ary"), "ary");
-  auto* idx =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("idx"), "idx");
+  auto* ary = Expr("ary");
+  auto* idx = Expr("idx");
 
-  ArrayAccessorExpression exp(Source{Source::Location{20, 2}}, ary, idx);
-  auto src = exp.source();
+  auto* exp = create<ArrayAccessorExpression>(Source{Source::Location{20, 2}},
+                                              ary, idx);
+  auto src = exp->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(ArrayAccessorExpressionTest, IsArrayAccessor) {
-  auto* ary =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("ary"), "ary");
-  auto* idx =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("idx"), "idx");
+  auto* ary = Expr("ary");
+  auto* idx = Expr("idx");
 
-  ArrayAccessorExpression exp(Source{}, ary, idx);
-  EXPECT_TRUE(exp.Is<ArrayAccessorExpression>());
+  auto* exp = create<ArrayAccessorExpression>(ary, idx);
+  EXPECT_TRUE(exp->Is<ArrayAccessorExpression>());
 }
 
 TEST_F(ArrayAccessorExpressionTest, IsValid) {
-  auto* ary =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("ary"), "ary");
-  auto* idx =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("idx"), "idx");
+  auto* ary = Expr("ary");
+  auto* idx = Expr("idx");
 
-  ArrayAccessorExpression exp(Source{}, ary, idx);
-  EXPECT_TRUE(exp.IsValid());
+  auto* exp = create<ArrayAccessorExpression>(ary, idx);
+  EXPECT_TRUE(exp->IsValid());
 }
 
 TEST_F(ArrayAccessorExpressionTest, IsValid_MissingArray) {
-  auto* idx =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("idx"), "idx");
+  auto* idx = Expr("idx");
 
-  ArrayAccessorExpression exp(Source{}, nullptr, idx);
-  EXPECT_FALSE(exp.IsValid());
+  auto* exp = create<ArrayAccessorExpression>(nullptr, idx);
+  EXPECT_FALSE(exp->IsValid());
 }
 
 TEST_F(ArrayAccessorExpressionTest, IsValid_MissingIndex) {
-  auto* ary =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("ary"), "ary");
+  auto* ary = Expr("ary");
 
-  ArrayAccessorExpression exp(Source{}, ary, nullptr);
-  EXPECT_FALSE(exp.IsValid());
+  auto* exp = create<ArrayAccessorExpression>(ary, nullptr);
+  EXPECT_FALSE(exp->IsValid());
 }
 
 TEST_F(ArrayAccessorExpressionTest, IsValid_InvalidArray) {
-  auto* ary =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol(""), "");
-  auto* idx =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("idx"), "idx");
-  ArrayAccessorExpression exp(Source{}, ary, idx);
-  EXPECT_FALSE(exp.IsValid());
+  auto* ary = Expr("");
+  auto* idx = Expr("idx");
+  auto* exp = create<ArrayAccessorExpression>(ary, idx);
+  EXPECT_FALSE(exp->IsValid());
 }
 
 TEST_F(ArrayAccessorExpressionTest, IsValid_InvalidIndex) {
-  auto* ary =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("ary"), "ary");
-  auto* idx =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol(""), "");
-  ArrayAccessorExpression exp(Source{}, ary, idx);
-  EXPECT_FALSE(exp.IsValid());
+  auto* ary = Expr("ary");
+  auto* idx = Expr("");
+  auto* exp = create<ArrayAccessorExpression>(ary, idx);
+  EXPECT_FALSE(exp->IsValid());
 }
 
 TEST_F(ArrayAccessorExpressionTest, ToStr) {
-  auto* ary =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("ary"), "ary");
-  auto* idx =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("idx"), "idx");
+  auto* ary = Expr("ary");
+  auto* idx = Expr("idx");
 
-  ArrayAccessorExpression exp(Source{}, ary, idx);
+  auto* exp = create<ArrayAccessorExpression>(ary, idx);
   std::ostringstream out;
-  exp.to_str(out, 2);
+  exp->to_str(out, 2);
 
   EXPECT_EQ(demangle(out.str()), R"(  ArrayAccessor[not set]{
     Identifier[not set]{ary}
diff --git a/src/ast/assignment_statement_test.cc b/src/ast/assignment_statement_test.cc
index 951e32c..2d7055d 100644
--- a/src/ast/assignment_statement_test.cc
+++ b/src/ast/assignment_statement_test.cc
@@ -24,91 +24,76 @@
 using AssignmentStatementTest = TestHelper;
 
 TEST_F(AssignmentStatementTest, Creation) {
-  auto* lhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("lhs"), "lhs");
-  auto* rhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("rhs"), "rhs");
+  auto* lhs = Expr("lhs");
+  auto* rhs = Expr("rhs");
 
-  AssignmentStatement stmt(Source{}, lhs, rhs);
-  EXPECT_EQ(stmt.lhs(), lhs);
-  EXPECT_EQ(stmt.rhs(), rhs);
+  auto* stmt = create<AssignmentStatement>(lhs, rhs);
+  EXPECT_EQ(stmt->lhs(), lhs);
+  EXPECT_EQ(stmt->rhs(), rhs);
 }
 
 TEST_F(AssignmentStatementTest, CreationWithSource) {
-  auto* lhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("lhs"), "lhs");
-  auto* rhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("rhs"), "rhs");
+  auto* lhs = Expr("lhs");
+  auto* rhs = Expr("rhs");
 
-  AssignmentStatement stmt(Source{Source::Location{20, 2}}, lhs, rhs);
-  auto src = stmt.source();
+  auto* stmt =
+      create<AssignmentStatement>(Source{Source::Location{20, 2}}, lhs, rhs);
+  auto src = stmt->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(AssignmentStatementTest, IsAssign) {
-  auto* lhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("lhs"), "lhs");
-  auto* rhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("rhs"), "rhs");
+  auto* lhs = Expr("lhs");
+  auto* rhs = Expr("rhs");
 
-  AssignmentStatement stmt(Source{}, lhs, rhs);
-  EXPECT_TRUE(stmt.Is<AssignmentStatement>());
+  auto* stmt = create<AssignmentStatement>(lhs, rhs);
+  EXPECT_TRUE(stmt->Is<AssignmentStatement>());
 }
 
 TEST_F(AssignmentStatementTest, IsValid) {
-  auto* lhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("lhs"), "lhs");
-  auto* rhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("rhs"), "rhs");
+  auto* lhs = Expr("lhs");
+  auto* rhs = Expr("rhs");
 
-  AssignmentStatement stmt(Source{}, lhs, rhs);
-  EXPECT_TRUE(stmt.IsValid());
+  auto* stmt = create<AssignmentStatement>(lhs, rhs);
+  EXPECT_TRUE(stmt->IsValid());
 }
 
 TEST_F(AssignmentStatementTest, IsValid_MissingLHS) {
-  auto* rhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("rhs"), "rhs");
+  auto* rhs = Expr("rhs");
 
-  AssignmentStatement stmt(Source{}, nullptr, rhs);
-  EXPECT_FALSE(stmt.IsValid());
+  auto* stmt = create<AssignmentStatement>(nullptr, rhs);
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(AssignmentStatementTest, IsValid_MissingRHS) {
-  auto* lhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("lhs"), "lhs");
+  auto* lhs = Expr("lhs");
 
-  AssignmentStatement stmt(Source{}, lhs, nullptr);
-  EXPECT_FALSE(stmt.IsValid());
+  auto* stmt = create<AssignmentStatement>(lhs, nullptr);
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(AssignmentStatementTest, IsValid_InvalidLHS) {
-  auto* lhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol(""), "");
-  auto* rhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("rhs"), "rhs");
-  AssignmentStatement stmt(Source{}, lhs, rhs);
-  EXPECT_FALSE(stmt.IsValid());
+  auto* lhs = Expr("");
+  auto* rhs = Expr("rhs");
+  auto* stmt = create<AssignmentStatement>(lhs, rhs);
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(AssignmentStatementTest, IsValid_InvalidRHS) {
-  auto* lhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("lhs"), "lhs");
-  auto* rhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol(""), "");
-  AssignmentStatement stmt(Source{}, lhs, rhs);
-  EXPECT_FALSE(stmt.IsValid());
+  auto* lhs = Expr("lhs");
+  auto* rhs = Expr("");
+  auto* stmt = create<AssignmentStatement>(lhs, rhs);
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(AssignmentStatementTest, ToStr) {
-  auto* lhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("lhs"), "lhs");
-  auto* rhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("rhs"), "rhs");
+  auto* lhs = Expr("lhs");
+  auto* rhs = Expr("rhs");
 
-  AssignmentStatement stmt(Source{}, lhs, rhs);
+  auto* stmt = create<AssignmentStatement>(lhs, rhs);
   std::ostringstream out;
-  stmt.to_str(out, 2);
+  stmt->to_str(out, 2);
 
   EXPECT_EQ(demangle(out.str()), R"(  Assignment{
     Identifier[not set]{lhs}
diff --git a/src/ast/binary_expression_test.cc b/src/ast/binary_expression_test.cc
index 4758a25..432bc45 100644
--- a/src/ast/binary_expression_test.cc
+++ b/src/ast/binary_expression_test.cc
@@ -26,105 +26,87 @@
 using BinaryExpressionTest = TestHelper;
 
 TEST_F(BinaryExpressionTest, Creation) {
-  auto* lhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("lhs"), "lhs");
-  auto* rhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("rhs"), "rhs");
+  auto* lhs = Expr("lhs");
+  auto* rhs = Expr("rhs");
 
-  BinaryExpression r(Source{}, BinaryOp::kEqual, lhs, rhs);
-  EXPECT_EQ(r.lhs(), lhs);
-  EXPECT_EQ(r.rhs(), rhs);
-  EXPECT_EQ(r.op(), BinaryOp::kEqual);
+  auto* r = create<BinaryExpression>(BinaryOp::kEqual, lhs, rhs);
+  EXPECT_EQ(r->lhs(), lhs);
+  EXPECT_EQ(r->rhs(), rhs);
+  EXPECT_EQ(r->op(), BinaryOp::kEqual);
 }
 
 TEST_F(BinaryExpressionTest, Creation_WithSource) {
-  auto* lhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("lhs"), "lhs");
-  auto* rhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("rhs"), "rhs");
+  auto* lhs = Expr("lhs");
+  auto* rhs = Expr("rhs");
 
-  BinaryExpression r(Source{Source::Location{20, 2}}, BinaryOp::kEqual, lhs,
-                     rhs);
-  auto src = r.source();
+  auto* r = create<BinaryExpression>(Source{Source::Location{20, 2}},
+                                     BinaryOp::kEqual, lhs, rhs);
+  auto src = r->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(BinaryExpressionTest, IsBinary) {
-  auto* lhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("lhs"), "lhs");
-  auto* rhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("rhs"), "rhs");
+  auto* lhs = Expr("lhs");
+  auto* rhs = Expr("rhs");
 
-  BinaryExpression r(Source{}, BinaryOp::kEqual, lhs, rhs);
-  EXPECT_TRUE(r.Is<BinaryExpression>());
+  auto* r = create<BinaryExpression>(BinaryOp::kEqual, lhs, rhs);
+  EXPECT_TRUE(r->Is<BinaryExpression>());
 }
 
 TEST_F(BinaryExpressionTest, IsValid) {
-  auto* lhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("lhs"), "lhs");
-  auto* rhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("rhs"), "rhs");
+  auto* lhs = Expr("lhs");
+  auto* rhs = Expr("rhs");
 
-  BinaryExpression r(Source{}, BinaryOp::kEqual, lhs, rhs);
-  EXPECT_TRUE(r.IsValid());
+  auto* r = create<BinaryExpression>(BinaryOp::kEqual, lhs, rhs);
+  EXPECT_TRUE(r->IsValid());
 }
 
 TEST_F(BinaryExpressionTest, IsValid_Null_LHS) {
-  auto* rhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("rhs"), "rhs");
+  auto* rhs = Expr("rhs");
 
-  BinaryExpression r(Source{}, BinaryOp::kEqual, nullptr, rhs);
-  EXPECT_FALSE(r.IsValid());
+  auto* r = create<BinaryExpression>(BinaryOp::kEqual, nullptr, rhs);
+  EXPECT_FALSE(r->IsValid());
 }
 
 TEST_F(BinaryExpressionTest, IsValid_Invalid_LHS) {
-  auto* lhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol(""), "");
-  auto* rhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("rhs"), "rhs");
+  auto* lhs = Expr("");
+  auto* rhs = Expr("rhs");
 
-  BinaryExpression r(Source{}, BinaryOp::kEqual, lhs, rhs);
-  EXPECT_FALSE(r.IsValid());
+  auto* r = create<BinaryExpression>(BinaryOp::kEqual, lhs, rhs);
+  EXPECT_FALSE(r->IsValid());
 }
 
 TEST_F(BinaryExpressionTest, IsValid_Null_RHS) {
-  auto* lhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("lhs"), "lhs");
+  auto* lhs = Expr("lhs");
 
-  BinaryExpression r(Source{}, BinaryOp::kEqual, lhs, nullptr);
-  EXPECT_FALSE(r.IsValid());
+  auto* r = create<BinaryExpression>(BinaryOp::kEqual, lhs, nullptr);
+  EXPECT_FALSE(r->IsValid());
 }
 
 TEST_F(BinaryExpressionTest, IsValid_Invalid_RHS) {
-  auto* lhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("lhs"), "lhs");
-  auto* rhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol(""), "");
+  auto* lhs = Expr("lhs");
+  auto* rhs = Expr("");
 
-  BinaryExpression r(Source{}, BinaryOp::kEqual, lhs, rhs);
-  EXPECT_FALSE(r.IsValid());
+  auto* r = create<BinaryExpression>(BinaryOp::kEqual, lhs, rhs);
+  EXPECT_FALSE(r->IsValid());
 }
 
 TEST_F(BinaryExpressionTest, IsValid_Binary_None) {
-  auto* lhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("lhs"), "lhs");
-  auto* rhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("rhs"), "rhs");
+  auto* lhs = Expr("lhs");
+  auto* rhs = Expr("rhs");
 
-  BinaryExpression r(Source{}, BinaryOp::kNone, lhs, rhs);
-  EXPECT_FALSE(r.IsValid());
+  auto* r = create<BinaryExpression>(BinaryOp::kNone, lhs, rhs);
+  EXPECT_FALSE(r->IsValid());
 }
 
 TEST_F(BinaryExpressionTest, ToStr) {
-  auto* lhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("lhs"), "lhs");
-  auto* rhs =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol("rhs"), "rhs");
+  auto* lhs = Expr("lhs");
+  auto* rhs = Expr("rhs");
 
-  BinaryExpression r(Source{}, BinaryOp::kEqual, lhs, rhs);
+  auto* r = create<BinaryExpression>(BinaryOp::kEqual, lhs, rhs);
   std::ostringstream out;
-  r.to_str(out, 2);
+  r->to_str(out, 2);
   EXPECT_EQ(demangle(out.str()), R"(  Binary[not set]{
     Identifier[not set]{lhs}
     equal
diff --git a/src/ast/binding_decoration_test.cc b/src/ast/binding_decoration_test.cc
index 5824236..08cde4c 100644
--- a/src/ast/binding_decoration_test.cc
+++ b/src/ast/binding_decoration_test.cc
@@ -24,13 +24,12 @@
 using BindingDecorationTest = TestHelper;
 
 TEST_F(BindingDecorationTest, Creation) {
-  BindingDecoration d{Source{}, 2};
-  EXPECT_EQ(2u, d.value());
+  auto* d = create<BindingDecoration>(2);
+  EXPECT_EQ(2u, d->value());
 }
 
 TEST_F(BindingDecorationTest, Is) {
-  BindingDecoration bd{Source{}, 2};
-  Decoration* d = &bd;
+  Decoration* d = create<BindingDecoration>(2);
   EXPECT_TRUE(d->Is<BindingDecoration>());
   EXPECT_FALSE(d->Is<BuiltinDecoration>());
   EXPECT_FALSE(d->Is<ConstantIdDecoration>());
@@ -39,9 +38,9 @@
 }
 
 TEST_F(BindingDecorationTest, ToStr) {
-  BindingDecoration d{Source{}, 2};
+  auto* d = create<BindingDecoration>(2);
   std::ostringstream out;
-  d.to_str(out, 0);
+  d->to_str(out, 0);
   EXPECT_EQ(out.str(), R"(BindingDecoration{2}
 )");
 }
diff --git a/src/ast/bitcast_expression_test.cc b/src/ast/bitcast_expression_test.cc
index 21d8832..dcbd774 100644
--- a/src/ast/bitcast_expression_test.cc
+++ b/src/ast/bitcast_expression_test.cc
@@ -25,75 +25,61 @@
 using BitcastExpressionTest = TestHelper;
 
 TEST_F(BitcastExpressionTest, Create) {
-  type::F32 f32;
-  auto* expr = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("expr"), "expr");
+  auto* expr = Expr("expr");
 
-  BitcastExpression exp(Source{}, &f32, expr);
-  ASSERT_EQ(exp.type(), &f32);
-  ASSERT_EQ(exp.expr(), expr);
+  auto* exp = create<BitcastExpression>(ty.f32, expr);
+  ASSERT_EQ(exp->type(), ty.f32);
+  ASSERT_EQ(exp->expr(), expr);
 }
 
 TEST_F(BitcastExpressionTest, CreateWithSource) {
-  type::F32 f32;
-  auto* expr = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("expr"), "expr");
+  auto* expr = Expr("expr");
 
-  BitcastExpression exp(Source{Source::Location{20, 2}}, &f32, expr);
-  auto src = exp.source();
+  auto* exp =
+      create<BitcastExpression>(Source{Source::Location{20, 2}}, ty.f32, expr);
+  auto src = exp->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(BitcastExpressionTest, IsBitcast) {
-  type::F32 f32;
-  auto* expr = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("expr"), "expr");
+  auto* expr = Expr("expr");
 
-  BitcastExpression exp(Source{}, &f32, expr);
-  EXPECT_TRUE(exp.Is<BitcastExpression>());
+  auto* exp = create<BitcastExpression>(ty.f32, expr);
+  EXPECT_TRUE(exp->Is<BitcastExpression>());
 }
 
 TEST_F(BitcastExpressionTest, IsValid) {
-  type::F32 f32;
-  auto* expr = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("expr"), "expr");
+  auto* expr = Expr("expr");
 
-  BitcastExpression exp(Source{}, &f32, expr);
-  EXPECT_TRUE(exp.IsValid());
+  auto* exp = create<BitcastExpression>(ty.f32, expr);
+  EXPECT_TRUE(exp->IsValid());
 }
 
 TEST_F(BitcastExpressionTest, IsValid_MissingType) {
-  auto* expr = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("expr"), "expr");
+  auto* expr = Expr("expr");
 
-  BitcastExpression exp(Source{}, nullptr, expr);
-  EXPECT_FALSE(exp.IsValid());
+  auto* exp = create<BitcastExpression>(nullptr, expr);
+  EXPECT_FALSE(exp->IsValid());
 }
 
 TEST_F(BitcastExpressionTest, IsValid_MissingExpr) {
-  type::F32 f32;
-
-  BitcastExpression exp(Source{}, &f32, nullptr);
-  EXPECT_FALSE(exp.IsValid());
+  auto* exp = create<BitcastExpression>(ty.f32, nullptr);
+  EXPECT_FALSE(exp->IsValid());
 }
 
 TEST_F(BitcastExpressionTest, IsValid_InvalidExpr) {
-  type::F32 f32;
-  auto* expr =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol(""), "");
-  BitcastExpression e(Source{}, &f32, expr);
-  EXPECT_FALSE(e.IsValid());
+  auto* expr = Expr("");
+  auto* e = create<BitcastExpression>(ty.f32, expr);
+  EXPECT_FALSE(e->IsValid());
 }
 
 TEST_F(BitcastExpressionTest, ToStr) {
-  type::F32 f32;
-  auto* expr = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("expr"), "expr");
+  auto* expr = Expr("expr");
 
-  BitcastExpression exp(Source{}, &f32, expr);
+  auto* exp = create<BitcastExpression>(ty.f32, expr);
   std::ostringstream out;
-  exp.to_str(out, 2);
+  exp->to_str(out, 2);
 
   EXPECT_EQ(demangle(out.str()), R"(  Bitcast[not set]<__f32>{
     Identifier[not set]{expr}
diff --git a/src/ast/block_statement_test.cc b/src/ast/block_statement_test.cc
index 78134c6..02c536e 100644
--- a/src/ast/block_statement_test.cc
+++ b/src/ast/block_statement_test.cc
@@ -28,66 +28,66 @@
 using BlockStatementTest = TestHelper;
 
 TEST_F(BlockStatementTest, Creation) {
-  auto* d = create<DiscardStatement>(Source{});
+  auto* d = create<DiscardStatement>();
   auto* ptr = d;
 
-  BlockStatement b(Source{}, StatementList{d});
+  auto* b = create<BlockStatement>(StatementList{d});
 
-  ASSERT_EQ(b.size(), 1u);
-  EXPECT_EQ(b[0], ptr);
+  ASSERT_EQ(b->size(), 1u);
+  EXPECT_EQ((*b)[0], ptr);
 }
 
 TEST_F(BlockStatementTest, Creation_WithSource) {
-  BlockStatement b(Source{Source::Location{20, 2}}, ast::StatementList{});
-  auto src = b.source();
+  auto* b = create<BlockStatement>(Source{Source::Location{20, 2}},
+                                   ast::StatementList{});
+  auto src = b->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(BlockStatementTest, IsBlock) {
-  BlockStatement b(Source{}, ast::StatementList{});
-  EXPECT_TRUE(b.Is<BlockStatement>());
+  auto* b = create<BlockStatement>(ast::StatementList{});
+  EXPECT_TRUE(b->Is<BlockStatement>());
 }
 
 TEST_F(BlockStatementTest, IsValid) {
-  BlockStatement b(Source{}, ast::StatementList{
-                                 create<DiscardStatement>(Source{}),
-                             });
-  EXPECT_TRUE(b.IsValid());
+  auto* b = create<BlockStatement>(ast::StatementList{
+      create<DiscardStatement>(),
+  });
+  EXPECT_TRUE(b->IsValid());
 }
 
 TEST_F(BlockStatementTest, IsValid_Empty) {
-  BlockStatement b(Source{}, ast::StatementList{});
-  EXPECT_TRUE(b.IsValid());
+  auto* b = create<BlockStatement>(ast::StatementList{});
+  EXPECT_TRUE(b->IsValid());
 }
 
 TEST_F(BlockStatementTest, IsValid_NullBodyStatement) {
-  BlockStatement b(Source{}, ast::StatementList{
-                                 create<DiscardStatement>(Source{}),
-                                 nullptr,
-                             });
+  auto* b = create<BlockStatement>(ast::StatementList{
+      create<DiscardStatement>(),
+      nullptr,
+  });
 
-  EXPECT_FALSE(b.IsValid());
+  EXPECT_FALSE(b->IsValid());
 }
 
 TEST_F(BlockStatementTest, IsValid_InvalidBodyStatement) {
-  BlockStatement b(
-      Source{},
+  auto* b = create<BlockStatement>(
+
       ast::StatementList{
-          create<IfStatement>(Source{}, nullptr,
-                              create<BlockStatement>(Source{}, StatementList{}),
+          create<IfStatement>(nullptr, create<BlockStatement>(StatementList{}),
                               ElseStatementList{}),
       });
-  EXPECT_FALSE(b.IsValid());
+  EXPECT_FALSE(b->IsValid());
 }
 
 TEST_F(BlockStatementTest, ToStr) {
-  BlockStatement b(Source{}, ast::StatementList{
-                                 create<DiscardStatement>(Source{}),
-                             });
+  auto* b = create<BlockStatement>(ast::StatementList{
+      create<DiscardStatement>(),
+  });
 
   std::ostringstream out;
-  b.to_str(out, 2);
+  b->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(  Block{
     Discard{}
   }
diff --git a/src/ast/bool_literal_test.cc b/src/ast/bool_literal_test.cc
index d98f988..97a9d5d 100644
--- a/src/ast/bool_literal_test.cc
+++ b/src/ast/bool_literal_test.cc
@@ -29,24 +29,23 @@
 
 TEST_F(BoolLiteralTest, True) {
   type::Bool bool_type;
-  BoolLiteral b{Source{}, &bool_type, true};
-  ASSERT_TRUE(b.Is<BoolLiteral>());
-  ASSERT_TRUE(b.IsTrue());
-  ASSERT_FALSE(b.IsFalse());
+  auto* b = create<BoolLiteral>(&bool_type, true);
+  ASSERT_TRUE(b->Is<BoolLiteral>());
+  ASSERT_TRUE(b->IsTrue());
+  ASSERT_FALSE(b->IsFalse());
 }
 
 TEST_F(BoolLiteralTest, False) {
   type::Bool bool_type;
-  BoolLiteral b{Source{}, &bool_type, false};
-  ASSERT_TRUE(b.Is<BoolLiteral>());
-  ASSERT_FALSE(b.IsTrue());
-  ASSERT_TRUE(b.IsFalse());
+  auto* b = create<BoolLiteral>(&bool_type, false);
+  ASSERT_TRUE(b->Is<BoolLiteral>());
+  ASSERT_FALSE(b->IsTrue());
+  ASSERT_TRUE(b->IsFalse());
 }
 
 TEST_F(BoolLiteralTest, Is) {
   type::Bool bool_type;
-  BoolLiteral b{Source{}, &bool_type, false};
-  Literal* l = &b;
+  ast::Literal* l = create<BoolLiteral>(&bool_type, false);
   EXPECT_TRUE(l->Is<BoolLiteral>());
   EXPECT_FALSE(l->Is<SintLiteral>());
   EXPECT_FALSE(l->Is<FloatLiteral>());
@@ -57,11 +56,11 @@
 
 TEST_F(BoolLiteralTest, ToStr) {
   type::Bool bool_type;
-  BoolLiteral t{Source{}, &bool_type, true};
-  BoolLiteral f{Source{}, &bool_type, false};
+  auto* t = create<BoolLiteral>(&bool_type, true);
+  auto* f = create<BoolLiteral>(&bool_type, false);
 
-  EXPECT_EQ(t.to_str(), "true");
-  EXPECT_EQ(f.to_str(), "false");
+  EXPECT_EQ(t->to_str(), "true");
+  EXPECT_EQ(f->to_str(), "false");
 }
 
 }  // namespace
diff --git a/src/ast/break_statement_test.cc b/src/ast/break_statement_test.cc
index 27a7a8f..10063a4 100644
--- a/src/ast/break_statement_test.cc
+++ b/src/ast/break_statement_test.cc
@@ -23,26 +23,26 @@
 using BreakStatementTest = TestHelper;
 
 TEST_F(BreakStatementTest, Creation_WithSource) {
-  BreakStatement stmt(Source{Source::Location{20, 2}});
-  auto src = stmt.source();
+  auto* stmt = create<BreakStatement>(Source{Source::Location{20, 2}});
+  auto src = stmt->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(BreakStatementTest, IsBreak) {
-  BreakStatement stmt(Source{});
-  EXPECT_TRUE(stmt.Is<BreakStatement>());
+  auto* stmt = create<BreakStatement>();
+  EXPECT_TRUE(stmt->Is<BreakStatement>());
 }
 
 TEST_F(BreakStatementTest, IsValid) {
-  BreakStatement stmt(Source{});
-  EXPECT_TRUE(stmt.IsValid());
+  auto* stmt = create<BreakStatement>();
+  EXPECT_TRUE(stmt->IsValid());
 }
 
 TEST_F(BreakStatementTest, ToStr) {
-  BreakStatement stmt(Source{});
+  auto* stmt = create<BreakStatement>();
   std::ostringstream out;
-  stmt.to_str(out, 2);
+  stmt->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(  Break{}
 )");
 }
diff --git a/src/ast/builder.cc b/src/ast/builder.cc
index 2c7479c..f9b96a7 100644
--- a/src/ast/builder.cc
+++ b/src/ast/builder.cc
@@ -40,8 +40,20 @@
                        type::Type* type,
                        Expression* constructor,
                        VariableDecorationList decorations) {
-  auto* var = create<Variable>(Source{}, name, storage, type, false,
-                               constructor, decorations);
+  auto* var =
+      create<Variable>(name, storage, type, false, constructor, decorations);
+  OnVariableBuilt(var);
+  return var;
+}
+
+Variable* Builder::Var(const Source& source,
+                       const std::string& name,
+                       StorageClass storage,
+                       type::Type* type,
+                       Expression* constructor,
+                       VariableDecorationList decorations) {
+  auto* var = create<Variable>(source, name, storage, type, false, constructor,
+                               decorations);
   OnVariableBuilt(var);
   return var;
 }
@@ -57,8 +69,8 @@
                          type::Type* type,
                          Expression* constructor,
                          VariableDecorationList decorations) {
-  auto* var = create<Variable>(Source{}, name, storage, type, true, constructor,
-                               decorations);
+  auto* var =
+      create<Variable>(name, storage, type, true, constructor, decorations);
   OnVariableBuilt(var);
   return var;
 }
diff --git a/src/ast/builder.h b/src/ast/builder.h
index 254bd1f..42efe59 100644
--- a/src/ast/builder.h
+++ b/src/ast/builder.h
@@ -464,6 +464,20 @@
                 Expression* constructor,
                 VariableDecorationList decorations);
 
+  /// @param source the variable source
+  /// @param name the variable name
+  /// @param storage the variable storage class
+  /// @param type the variable type
+  /// @param constructor constructor expression
+  /// @param decorations variable decorations
+  /// @returns a `Variable` with the given name, storage and type
+  Variable* Var(const Source& source,
+                const std::string& name,
+                StorageClass storage,
+                type::Type* type,
+                Expression* constructor,
+                VariableDecorationList decorations);
+
   /// @param name the variable name
   /// @param storage the variable storage class
   /// @param type the variable type
diff --git a/src/ast/builtin_decoration_test.cc b/src/ast/builtin_decoration_test.cc
index 0618f65..bee20b4 100644
--- a/src/ast/builtin_decoration_test.cc
+++ b/src/ast/builtin_decoration_test.cc
@@ -8,7 +8,7 @@
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied->
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
@@ -24,13 +24,12 @@
 using BuiltinDecorationTest = TestHelper;
 
 TEST_F(BuiltinDecorationTest, Creation) {
-  BuiltinDecoration d{Source{}, Builtin::kFragDepth};
-  EXPECT_EQ(Builtin::kFragDepth, d.value());
+  auto* d = create<BuiltinDecoration>(Builtin::kFragDepth);
+  EXPECT_EQ(Builtin::kFragDepth, d->value());
 }
 
 TEST_F(BuiltinDecorationTest, Is) {
-  BuiltinDecoration bd{Source{}, Builtin::kFragDepth};
-  Decoration* d = &bd;
+  Decoration* d = create<BuiltinDecoration>(Builtin::kFragDepth);
   EXPECT_FALSE(d->Is<BindingDecoration>());
   EXPECT_TRUE(d->Is<BuiltinDecoration>());
   EXPECT_FALSE(d->Is<ConstantIdDecoration>());
@@ -39,9 +38,9 @@
 }
 
 TEST_F(BuiltinDecorationTest, ToStr) {
-  BuiltinDecoration d{Source{}, Builtin::kFragDepth};
+  auto* d = create<BuiltinDecoration>(Builtin::kFragDepth);
   std::ostringstream out;
-  d.to_str(out, 0);
+  d->to_str(out, 0);
   EXPECT_EQ(out.str(), R"(BuiltinDecoration{frag_depth}
 )");
 }
diff --git a/src/ast/call_expression_test.cc b/src/ast/call_expression_test.cc
index 08e8324..8769a52 100644
--- a/src/ast/call_expression_test.cc
+++ b/src/ast/call_expression_test.cc
@@ -24,93 +24,80 @@
 using CallExpressionTest = TestHelper;
 
 TEST_F(CallExpressionTest, Creation) {
-  auto* func = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("func"), "func");
+  auto* func = Expr("func");
   ExpressionList params;
-  params.push_back(create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("param1"), "param1"));
-  params.push_back(create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("param2"), "param2"));
+  params.push_back(Expr("param1"));
+  params.push_back(Expr("param2"));
 
-  CallExpression stmt(Source{}, func, params);
-  EXPECT_EQ(stmt.func(), func);
+  auto* stmt = create<CallExpression>(func, params);
+  EXPECT_EQ(stmt->func(), func);
 
-  const auto& vec = stmt.params();
+  const auto& vec = stmt->params();
   ASSERT_EQ(vec.size(), 2u);
   EXPECT_EQ(vec[0], params[0]);
   EXPECT_EQ(vec[1], params[1]);
 }
 
 TEST_F(CallExpressionTest, Creation_WithSource) {
-  auto* func = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("func"), "func");
-  CallExpression stmt(Source{Source::Location{20, 2}}, func, {});
-  auto src = stmt.source();
+  auto* func = Expr("func");
+  auto* stmt = create<CallExpression>(Source{Source::Location{20, 2}}, func,
+                                      ExpressionList{});
+  auto src = stmt->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(CallExpressionTest, IsCall) {
-  auto* func = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("func"), "func");
-  CallExpression stmt(Source{}, func, {});
-  EXPECT_TRUE(stmt.Is<CallExpression>());
+  auto* func = Expr("func");
+  auto* stmt = create<CallExpression>(func, ExpressionList{});
+  EXPECT_TRUE(stmt->Is<CallExpression>());
 }
 
 TEST_F(CallExpressionTest, IsValid) {
-  auto* func = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("func"), "func");
-  CallExpression stmt(Source{}, func, {});
-  EXPECT_TRUE(stmt.IsValid());
+  auto* func = Expr("func");
+  auto* stmt = create<CallExpression>(func, ExpressionList{});
+  EXPECT_TRUE(stmt->IsValid());
 }
 
 TEST_F(CallExpressionTest, IsValid_MissingFunction) {
-  CallExpression stmt(Source{}, nullptr, {});
-  EXPECT_FALSE(stmt.IsValid());
+  auto* stmt = create<CallExpression>(nullptr, ExpressionList{});
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(CallExpressionTest, IsValid_NullParam) {
-  auto* func = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("func"), "func");
+  auto* func = Expr("func");
   ExpressionList params;
-  params.push_back(create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("param1"), "param1"));
+  params.push_back(Expr("param1"));
   params.push_back(nullptr);
-  params.push_back(create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("param2"), "param2"));
+  params.push_back(Expr("param2"));
 
-  CallExpression stmt(Source{}, func, params);
-  EXPECT_FALSE(stmt.IsValid());
+  auto* stmt = create<CallExpression>(func, params);
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(CallExpressionTest, IsValid_InvalidFunction) {
-  auto* func =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol(""), "");
+  auto* func = Expr("");
   ExpressionList params;
-  params.push_back(create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("param1"), "param1"));
+  params.push_back(Expr("param1"));
 
-  CallExpression stmt(Source{}, func, params);
-  EXPECT_FALSE(stmt.IsValid());
+  auto* stmt = create<CallExpression>(func, params);
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(CallExpressionTest, IsValid_InvalidParam) {
-  auto* func = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("func"), "func");
+  auto* func = Expr("func");
   ExpressionList params;
-  params.push_back(
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol(""), ""));
+  params.push_back(Expr(""));
 
-  CallExpression stmt(Source{}, func, params);
-  EXPECT_FALSE(stmt.IsValid());
+  auto* stmt = create<CallExpression>(func, params);
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(CallExpressionTest, ToStr_NoParams) {
-  auto* func = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("func"), "func");
-  CallExpression stmt(Source{}, func, {});
+  auto* func = Expr("func");
+  auto* stmt = create<CallExpression>(func, ExpressionList{});
   std::ostringstream out;
-  stmt.to_str(out, 2);
+  stmt->to_str(out, 2);
   EXPECT_EQ(demangle(out.str()), R"(  Call[not set]{
     Identifier[not set]{func}
     (
@@ -120,17 +107,14 @@
 }
 
 TEST_F(CallExpressionTest, ToStr_WithParams) {
-  auto* func = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("func"), "func");
+  auto* func = Expr("func");
   ExpressionList params;
-  params.push_back(create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("param1"), "param1"));
-  params.push_back(create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("param2"), "param2"));
+  params.push_back(Expr("param1"));
+  params.push_back(Expr("param2"));
 
-  CallExpression stmt(Source{}, func, params);
+  auto* stmt = create<CallExpression>(func, params);
   std::ostringstream out;
-  stmt.to_str(out, 2);
+  stmt->to_str(out, 2);
   EXPECT_EQ(demangle(out.str()), R"(  Call[not set]{
     Identifier[not set]{func}
     (
diff --git a/src/ast/call_statement_test.cc b/src/ast/call_statement_test.cc
index b6fcee2..a9545e2 100644
--- a/src/ast/call_statement_test.cc
+++ b/src/ast/call_statement_test.cc
@@ -25,52 +25,40 @@
 using CallStatementTest = TestHelper;
 
 TEST_F(CallStatementTest, Creation) {
-  auto* expr =
-      create<CallExpression>(Source{},
-                             create<IdentifierExpression>(
-                                 Source{}, mod.RegisterSymbol("func"), "func"),
-                             ExpressionList{});
+  auto* expr = create<CallExpression>(Expr("func"), ExpressionList{});
 
-  CallStatement c(Source{}, expr);
-  EXPECT_EQ(c.expr(), expr);
+  auto* c = create<CallStatement>(expr);
+  EXPECT_EQ(c->expr(), expr);
 }
 
 TEST_F(CallStatementTest, IsCall) {
-  CallStatement c(Source{}, nullptr);
-  EXPECT_TRUE(c.Is<CallStatement>());
+  auto* c = create<CallStatement>(nullptr);
+  EXPECT_TRUE(c->Is<CallStatement>());
 }
 
 TEST_F(CallStatementTest, IsValid) {
-  CallStatement c(
-      Source{},
-      create<CallExpression>(Source{},
-                             create<IdentifierExpression>(
-                                 Source{}, mod.RegisterSymbol("func"), "func"),
-                             ExpressionList{}));
-  EXPECT_TRUE(c.IsValid());
+  auto* c = create<CallStatement>(
+      create<CallExpression>(Expr("func"), ExpressionList{}));
+  EXPECT_TRUE(c->IsValid());
 }
 
 TEST_F(CallStatementTest, IsValid_MissingExpr) {
-  CallStatement c(Source{}, nullptr);
-  EXPECT_FALSE(c.IsValid());
+  auto* c = create<CallStatement>(nullptr);
+  EXPECT_FALSE(c->IsValid());
 }
 
 TEST_F(CallStatementTest, IsValid_InvalidExpr) {
-  CallExpression stmt(Source{}, nullptr, {});
-  CallStatement c(Source{}, &stmt);
-  EXPECT_FALSE(c.IsValid());
+  auto* c = create<CallStatement>(
+      create<CallExpression>(nullptr, ast::ExpressionList{}));
+  EXPECT_FALSE(c->IsValid());
 }
 
 TEST_F(CallStatementTest, ToStr) {
-  CallStatement c(
-      Source{},
-      create<CallExpression>(Source{},
-                             create<IdentifierExpression>(
-                                 Source{}, mod.RegisterSymbol("func"), "func"),
-                             ExpressionList{}));
+  auto* c = create<CallStatement>(
+      create<CallExpression>(Expr("func"), ExpressionList{}));
 
   std::ostringstream out;
-  c.to_str(out, 2);
+  c->to_str(out, 2);
   EXPECT_EQ(demangle(out.str()), R"(  Call[not set]{
     Identifier[not set]{func}
     (
diff --git a/src/ast/case_statement_test.cc b/src/ast/case_statement_test.cc
index 95714ad..ce858df 100644
--- a/src/ast/case_statement_test.cc
+++ b/src/ast/case_statement_test.cc
@@ -29,128 +29,113 @@
 using CaseStatementTest = TestHelper;
 
 TEST_F(CaseStatementTest, Creation_i32) {
-  type::I32 i32;
-
   CaseSelectorList b;
-  auto* selector = create<SintLiteral>(Source{}, &i32, 2);
+  auto* selector = create<SintLiteral>(ty.i32, 2);
   b.push_back(selector);
 
-  auto* discard = create<DiscardStatement>(Source{});
-  auto* body = create<BlockStatement>(Source{}, StatementList{discard});
+  auto* discard = create<DiscardStatement>();
+  auto* body = create<BlockStatement>(StatementList{discard});
 
-  CaseStatement c(Source{}, b, body);
-  ASSERT_EQ(c.selectors().size(), 1u);
-  EXPECT_EQ(c.selectors()[0], selector);
-  ASSERT_EQ(c.body()->size(), 1u);
-  EXPECT_EQ(c.body()->get(0), discard);
+  auto* c = create<CaseStatement>(b, body);
+  ASSERT_EQ(c->selectors().size(), 1u);
+  EXPECT_EQ(c->selectors()[0], selector);
+  ASSERT_EQ(c->body()->size(), 1u);
+  EXPECT_EQ(c->body()->get(0), discard);
 }
 
 TEST_F(CaseStatementTest, Creation_u32) {
-  type::U32 u32;
-
   CaseSelectorList b;
-  auto* selector = create<SintLiteral>(Source{}, &u32, 2);
+  auto* selector = create<SintLiteral>(ty.u32, 2);
   b.push_back(selector);
 
-  auto* discard = create<DiscardStatement>(Source{});
-  auto* body = create<BlockStatement>(Source{}, StatementList{discard});
+  auto* discard = create<DiscardStatement>();
+  auto* body = create<BlockStatement>(StatementList{discard});
 
-  CaseStatement c(Source{}, b, body);
-  ASSERT_EQ(c.selectors().size(), 1u);
-  EXPECT_EQ(c.selectors()[0], selector);
-  ASSERT_EQ(c.body()->size(), 1u);
-  EXPECT_EQ(c.body()->get(0), discard);
+  auto* c = create<CaseStatement>(b, body);
+  ASSERT_EQ(c->selectors().size(), 1u);
+  EXPECT_EQ(c->selectors()[0], selector);
+  ASSERT_EQ(c->body()->size(), 1u);
+  EXPECT_EQ(c->body()->get(0), discard);
 }
 
 TEST_F(CaseStatementTest, Creation_WithSource) {
-  type::I32 i32;
   CaseSelectorList b;
-  b.push_back(create<SintLiteral>(Source{}, &i32, 2));
+  b.push_back(create<SintLiteral>(ty.i32, 2));
 
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                       });
-  CaseStatement c(Source{Source::Location{20, 2}}, b, body);
-  auto src = c.source();
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+  });
+  auto* c = create<CaseStatement>(Source{Source::Location{20, 2}}, b, body);
+  auto src = c->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(CaseStatementTest, IsDefault_WithoutSelectors) {
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                       });
-  CaseStatement c(Source{}, CaseSelectorList{}, body);
-  EXPECT_TRUE(c.IsDefault());
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+  });
+  auto* c = create<CaseStatement>(CaseSelectorList{}, body);
+  EXPECT_TRUE(c->IsDefault());
 }
 
 TEST_F(CaseStatementTest, IsDefault_WithSelectors) {
-  type::I32 i32;
   CaseSelectorList b;
-  b.push_back(create<SintLiteral>(Source{}, &i32, 2));
+  b.push_back(create<SintLiteral>(ty.i32, 2));
 
-  CaseStatement c(Source{}, b,
-                  create<BlockStatement>(Source{}, StatementList{}));
-  EXPECT_FALSE(c.IsDefault());
+  auto* c = create<CaseStatement>(b, create<BlockStatement>(StatementList{}));
+  EXPECT_FALSE(c->IsDefault());
 }
 
 TEST_F(CaseStatementTest, IsCase) {
-  CaseStatement c(Source{}, CaseSelectorList{},
-                  create<BlockStatement>(Source{}, StatementList{}));
-  EXPECT_TRUE(c.Is<CaseStatement>());
+  auto* c = create<CaseStatement>(CaseSelectorList{},
+                                  create<BlockStatement>(StatementList{}));
+  EXPECT_TRUE(c->Is<CaseStatement>());
 }
 
 TEST_F(CaseStatementTest, IsValid) {
-  CaseStatement c(Source{}, CaseSelectorList{},
-                  create<BlockStatement>(Source{}, StatementList{}));
-  EXPECT_TRUE(c.IsValid());
+  auto* c = create<CaseStatement>(CaseSelectorList{},
+                                  create<BlockStatement>(StatementList{}));
+  EXPECT_TRUE(c->IsValid());
 }
 
 TEST_F(CaseStatementTest, IsValid_NullBodyStatement) {
-  type::I32 i32;
   CaseSelectorList b;
-  b.push_back(create<SintLiteral>(Source{}, &i32, 2));
+  b.push_back(create<SintLiteral>(ty.i32, 2));
 
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                           nullptr,
-                                       });
-  CaseStatement c(Source{}, b, body);
-  EXPECT_FALSE(c.IsValid());
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+      nullptr,
+  });
+  auto* c = create<CaseStatement>(b, body);
+  EXPECT_FALSE(c->IsValid());
 }
 
 TEST_F(CaseStatementTest, IsValid_InvalidBodyStatement) {
-  type::I32 i32;
   CaseSelectorList b;
-  b.push_back(create<SintLiteral>(Source{}, &i32, 2));
+  b.push_back(create<SintLiteral>(ty.i32, 2));
 
   auto* body = create<BlockStatement>(
-      Source{},
+
       StatementList{
-          create<IfStatement>(Source{}, nullptr,
-                              create<BlockStatement>(Source{}, StatementList{}),
+          create<IfStatement>(nullptr, create<BlockStatement>(StatementList{}),
                               ElseStatementList{}),
       });
-  CaseStatement c(Source{}, {b}, body);
-  EXPECT_FALSE(c.IsValid());
+  auto* c = create<CaseStatement>(CaseSelectorList{b}, body);
+  EXPECT_FALSE(c->IsValid());
 }
 
 TEST_F(CaseStatementTest, ToStr_WithSelectors_i32) {
-  type::I32 i32;
   CaseSelectorList b;
-  b.push_back(create<SintLiteral>(Source{}, &i32, -2));
+  b.push_back(create<SintLiteral>(ty.i32, -2));
 
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                       });
-  CaseStatement c(Source{}, {b}, body);
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+  });
+  auto* c = create<CaseStatement>(CaseSelectorList{b}, body);
 
   std::ostringstream out;
-  c.to_str(out, 2);
+  c->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(  Case -2{
     Discard{}
   }
@@ -158,18 +143,16 @@
 }
 
 TEST_F(CaseStatementTest, ToStr_WithSelectors_u32) {
-  type::U32 u32;
   CaseSelectorList b;
-  b.push_back(create<UintLiteral>(Source{}, &u32, 2));
+  b.push_back(create<UintLiteral>(ty.u32, 2));
 
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                       });
-  CaseStatement c(Source{}, {b}, body);
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+  });
+  auto* c = create<CaseStatement>(CaseSelectorList{b}, body);
 
   std::ostringstream out;
-  c.to_str(out, 2);
+  c->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(  Case 2{
     Discard{}
   }
@@ -177,20 +160,17 @@
 }
 
 TEST_F(CaseStatementTest, ToStr_WithMultipleSelectors) {
-  type::I32 i32;
-
   CaseSelectorList b;
-  b.push_back(create<SintLiteral>(Source{}, &i32, 1));
-  b.push_back(create<SintLiteral>(Source{}, &i32, 2));
+  b.push_back(create<SintLiteral>(ty.i32, 1));
+  b.push_back(create<SintLiteral>(ty.i32, 2));
 
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                       });
-  CaseStatement c(Source{}, b, body);
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+  });
+  auto* c = create<CaseStatement>(b, body);
 
   std::ostringstream out;
-  c.to_str(out, 2);
+  c->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(  Case 1, 2{
     Discard{}
   }
@@ -198,14 +178,13 @@
 }
 
 TEST_F(CaseStatementTest, ToStr_WithoutSelectors) {
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                       });
-  CaseStatement c(Source{}, CaseSelectorList{}, body);
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+  });
+  auto* c = create<CaseStatement>(CaseSelectorList{}, body);
 
   std::ostringstream out;
-  c.to_str(out, 2);
+  c->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(  Default{
     Discard{}
   }
diff --git a/src/ast/clone_context.h b/src/ast/clone_context.h
index 9bfb906..05f11d6 100644
--- a/src/ast/clone_context.h
+++ b/src/ast/clone_context.h
@@ -78,7 +78,7 @@
   /// @return the cloned source
   Source Clone(const Source& s) { return s; }
 
-  /// Clones each of the elements of the vector `v` into the module #mod.
+  /// Clones each of the elements of the vector `v` into the module #mod->
   /// @param v the vector to clone
   /// @return the cloned vector
   template <typename T>
diff --git a/src/ast/constant_id_decoration_test.cc b/src/ast/constant_id_decoration_test.cc
index 493c6da..2da917a 100644
--- a/src/ast/constant_id_decoration_test.cc
+++ b/src/ast/constant_id_decoration_test.cc
@@ -23,13 +23,12 @@
 using ConstantIdDecorationTest = TestHelper;
 
 TEST_F(ConstantIdDecorationTest, Creation) {
-  ConstantIdDecoration d{Source{}, 12};
-  EXPECT_EQ(12u, d.value());
+  auto* d = create<ConstantIdDecoration>(12);
+  EXPECT_EQ(12u, d->value());
 }
 
 TEST_F(ConstantIdDecorationTest, Is) {
-  ConstantIdDecoration cd{Source{}, 27};
-  Decoration* d = &cd;
+  Decoration* d = create<ConstantIdDecoration>(27);
   EXPECT_FALSE(d->Is<BindingDecoration>());
   EXPECT_FALSE(d->Is<BuiltinDecoration>());
   EXPECT_TRUE(d->Is<ConstantIdDecoration>());
@@ -38,9 +37,9 @@
 }
 
 TEST_F(ConstantIdDecorationTest, ToStr) {
-  ConstantIdDecoration d{Source{}, 1200};
+  auto* d = create<ConstantIdDecoration>(1200);
   std::ostringstream out;
-  d.to_str(out, 0);
+  d->to_str(out, 0);
   EXPECT_EQ(out.str(), R"(ConstantIdDecoration{1200}
 )");
 }
diff --git a/src/ast/continue_statement_test.cc b/src/ast/continue_statement_test.cc
index 5c15b80..ab725b1 100644
--- a/src/ast/continue_statement_test.cc
+++ b/src/ast/continue_statement_test.cc
@@ -23,26 +23,26 @@
 using ContinueStatementTest = TestHelper;
 
 TEST_F(ContinueStatementTest, Creation_WithSource) {
-  ContinueStatement stmt(Source{Source::Location{20, 2}});
-  auto src = stmt.source();
+  auto* stmt = create<ContinueStatement>(Source{Source::Location{20, 2}});
+  auto src = stmt->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(ContinueStatementTest, IsContinue) {
-  ContinueStatement stmt(Source{});
-  EXPECT_TRUE(stmt.Is<ContinueStatement>());
+  auto* stmt = create<ContinueStatement>();
+  EXPECT_TRUE(stmt->Is<ContinueStatement>());
 }
 
 TEST_F(ContinueStatementTest, IsValid) {
-  ContinueStatement stmt(Source{});
-  EXPECT_TRUE(stmt.IsValid());
+  auto* stmt = create<ContinueStatement>();
+  EXPECT_TRUE(stmt->IsValid());
 }
 
 TEST_F(ContinueStatementTest, ToStr) {
-  ContinueStatement stmt(Source{});
+  auto* stmt = create<ContinueStatement>();
   std::ostringstream out;
-  stmt.to_str(out, 2);
+  stmt->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(  Continue{}
 )");
 }
diff --git a/src/ast/decoration_test.cc b/src/ast/decoration_test.cc
index 8ec0a01..ea8ac2a 100644
--- a/src/ast/decoration_test.cc
+++ b/src/ast/decoration_test.cc
@@ -43,21 +43,21 @@
 using DecorationTest = TestHelper;
 
 TEST_F(DecorationTest, AsCorrectType) {
-  auto* decoration = create<ConstantIdDecoration>(Source{}, 1);
+  auto* decoration = create<ConstantIdDecoration>(1);
   auto* upcast = static_cast<Decoration*>(decoration);
   auto* downcast = As<VariableDecoration>(upcast);
   EXPECT_EQ(decoration, downcast);
 }
 
 TEST_F(DecorationTest, AsIncorrectType) {
-  auto* decoration = create<ConstantIdDecoration>(Source{}, 1);
+  auto* decoration = create<ConstantIdDecoration>(1);
   auto* upcast = static_cast<Decoration*>(decoration);
   auto* downcast = As<ArrayDecoration>(upcast);
   EXPECT_EQ(nullptr, downcast);
 }
 
 TEST_F(DecorationTest, Is) {
-  Decoration* decoration = create<ConstantIdDecoration>(Source{}, 1);
+  Decoration* decoration = create<ConstantIdDecoration>(1);
   EXPECT_TRUE(decoration->Is<VariableDecoration>());
   EXPECT_FALSE(decoration->Is<ArrayDecoration>());
 }
diff --git a/src/ast/discard_statement_test.cc b/src/ast/discard_statement_test.cc
index 3cd5256..545d732 100644
--- a/src/ast/discard_statement_test.cc
+++ b/src/ast/discard_statement_test.cc
@@ -25,36 +25,36 @@
 using DiscardStatementTest = TestHelper;
 
 TEST_F(DiscardStatementTest, Creation) {
-  DiscardStatement stmt(Source{});
-  EXPECT_EQ(stmt.source().range.begin.line, 0u);
-  EXPECT_EQ(stmt.source().range.begin.column, 0u);
-  EXPECT_EQ(stmt.source().range.end.line, 0u);
-  EXPECT_EQ(stmt.source().range.end.column, 0u);
+  auto* stmt = create<DiscardStatement>();
+  EXPECT_EQ(stmt->source().range.begin.line, 0u);
+  EXPECT_EQ(stmt->source().range.begin.column, 0u);
+  EXPECT_EQ(stmt->source().range.end.line, 0u);
+  EXPECT_EQ(stmt->source().range.end.column, 0u);
 }
 
 TEST_F(DiscardStatementTest, Creation_WithSource) {
-  DiscardStatement stmt(
+  auto* stmt = create<DiscardStatement>(
       Source{Source::Range{Source::Location{20, 2}, Source::Location{20, 5}}});
-  EXPECT_EQ(stmt.source().range.begin.line, 20u);
-  EXPECT_EQ(stmt.source().range.begin.column, 2u);
-  EXPECT_EQ(stmt.source().range.end.line, 20u);
-  EXPECT_EQ(stmt.source().range.end.column, 5u);
+  EXPECT_EQ(stmt->source().range.begin.line, 20u);
+  EXPECT_EQ(stmt->source().range.begin.column, 2u);
+  EXPECT_EQ(stmt->source().range.end.line, 20u);
+  EXPECT_EQ(stmt->source().range.end.column, 5u);
 }
 
 TEST_F(DiscardStatementTest, IsDiscard) {
-  DiscardStatement stmt(Source{});
-  EXPECT_TRUE(stmt.Is<DiscardStatement>());
+  auto* stmt = create<DiscardStatement>();
+  EXPECT_TRUE(stmt->Is<DiscardStatement>());
 }
 
 TEST_F(DiscardStatementTest, IsValid) {
-  DiscardStatement stmt(Source{});
-  EXPECT_TRUE(stmt.IsValid());
+  auto* stmt = create<DiscardStatement>();
+  EXPECT_TRUE(stmt->IsValid());
 }
 
 TEST_F(DiscardStatementTest, ToStr) {
-  DiscardStatement stmt(Source{});
+  auto* stmt = create<DiscardStatement>();
   std::ostringstream out;
-  stmt.to_str(out, 2);
+  stmt->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(  Discard{}
 )");
 }
diff --git a/src/ast/else_statement_test.cc b/src/ast/else_statement_test.cc
index f1b681c..b9f1fd7 100644
--- a/src/ast/else_statement_test.cc
+++ b/src/ast/else_statement_test.cc
@@ -30,103 +30,98 @@
 TEST_F(ElseStatementTest, Creation) {
   type::Bool bool_type;
   auto* cond = create<ScalarConstructorExpression>(
-      Source{}, create<BoolLiteral>(Source{}, &bool_type, true));
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                       });
+      create<BoolLiteral>(&bool_type, true));
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+  });
   auto* discard = body->get(0);
 
-  ElseStatement e(Source{}, cond, body);
-  EXPECT_EQ(e.condition(), cond);
-  ASSERT_EQ(e.body()->size(), 1u);
-  EXPECT_EQ(e.body()->get(0), discard);
+  auto* e = create<ElseStatement>(cond, body);
+  EXPECT_EQ(e->condition(), cond);
+  ASSERT_EQ(e->body()->size(), 1u);
+  EXPECT_EQ(e->body()->get(0), discard);
 }
 
 TEST_F(ElseStatementTest, Creation_WithSource) {
-  ElseStatement e(Source{Source::Location{20, 2}}, nullptr,
-                  create<BlockStatement>(Source{}, StatementList{}));
-  auto src = e.source();
+  auto* e = create<ElseStatement>(Source{Source::Location{20, 2}}, nullptr,
+                                  create<BlockStatement>(StatementList{}));
+  auto src = e->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(ElseStatementTest, IsElse) {
-  ElseStatement e(Source{}, nullptr,
-                  create<BlockStatement>(Source{}, StatementList{}));
-  EXPECT_TRUE(e.Is<ElseStatement>());
+  auto* e =
+      create<ElseStatement>(nullptr, create<BlockStatement>(StatementList{}));
+  EXPECT_TRUE(e->Is<ElseStatement>());
 }
 
 TEST_F(ElseStatementTest, HasCondition) {
   type::Bool bool_type;
   auto* cond = create<ScalarConstructorExpression>(
-      Source{}, create<BoolLiteral>(Source{}, &bool_type, true));
-  ElseStatement e(Source{}, cond,
-                  create<BlockStatement>(Source{}, StatementList{}));
-  EXPECT_TRUE(e.HasCondition());
+      create<BoolLiteral>(&bool_type, true));
+  auto* e =
+      create<ElseStatement>(cond, create<BlockStatement>(StatementList{}));
+  EXPECT_TRUE(e->HasCondition());
 }
 
 TEST_F(ElseStatementTest, HasContition_NullCondition) {
-  ElseStatement e(Source{}, nullptr,
-                  create<BlockStatement>(Source{}, StatementList{}));
-  EXPECT_FALSE(e.HasCondition());
+  auto* e =
+      create<ElseStatement>(nullptr, create<BlockStatement>(StatementList{}));
+  EXPECT_FALSE(e->HasCondition());
 }
 
 TEST_F(ElseStatementTest, IsValid) {
-  ElseStatement e(Source{}, nullptr,
-                  create<BlockStatement>(Source{}, StatementList{}));
-  EXPECT_TRUE(e.IsValid());
+  auto* e =
+      create<ElseStatement>(nullptr, create<BlockStatement>(StatementList{}));
+  EXPECT_TRUE(e->IsValid());
 }
 
 TEST_F(ElseStatementTest, IsValid_WithBody) {
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                       });
-  ElseStatement e(Source{}, nullptr, body);
-  EXPECT_TRUE(e.IsValid());
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+  });
+  auto* e = create<ElseStatement>(nullptr, body);
+  EXPECT_TRUE(e->IsValid());
 }
 
 TEST_F(ElseStatementTest, IsValid_WithNullBodyStatement) {
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                           nullptr,
-                                       });
-  ElseStatement e(Source{}, nullptr, body);
-  EXPECT_FALSE(e.IsValid());
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+      nullptr,
+  });
+  auto* e = create<ElseStatement>(nullptr, body);
+  EXPECT_FALSE(e->IsValid());
 }
 
 TEST_F(ElseStatementTest, IsValid_InvalidCondition) {
-  auto* cond = create<ScalarConstructorExpression>(Source{}, nullptr);
-  ElseStatement e(Source{}, cond,
-                  create<BlockStatement>(Source{}, StatementList{}));
-  EXPECT_FALSE(e.IsValid());
+  auto* cond = create<ScalarConstructorExpression>(nullptr);
+  auto* e =
+      create<ElseStatement>(cond, create<BlockStatement>(StatementList{}));
+  EXPECT_FALSE(e->IsValid());
 }
 
 TEST_F(ElseStatementTest, IsValid_InvalidBodyStatement) {
   auto* body = create<BlockStatement>(
-      Source{},
+
       StatementList{
-          create<IfStatement>(Source{}, nullptr,
-                              create<BlockStatement>(Source{}, StatementList{}),
+          create<IfStatement>(nullptr, create<BlockStatement>(StatementList{}),
                               ElseStatementList{}),
       });
-  ElseStatement e(Source{}, nullptr, body);
-  EXPECT_FALSE(e.IsValid());
+  auto* e = create<ElseStatement>(nullptr, body);
+  EXPECT_FALSE(e->IsValid());
 }
 
 TEST_F(ElseStatementTest, ToStr) {
   type::Bool bool_type;
   auto* cond = create<ScalarConstructorExpression>(
-      Source{}, create<BoolLiteral>(Source{}, &bool_type, true));
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                       });
-  ElseStatement e(Source{}, cond, body);
+      create<BoolLiteral>(&bool_type, true));
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+  });
+  auto* e = create<ElseStatement>(cond, body);
   std::ostringstream out;
-  e.to_str(out, 2);
+  e->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(  Else{
     (
       ScalarConstructor[not set]{true}
@@ -139,13 +134,12 @@
 }
 
 TEST_F(ElseStatementTest, ToStr_NoCondition) {
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                       });
-  ElseStatement e(Source{}, nullptr, body);
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+  });
+  auto* e = create<ElseStatement>(nullptr, body);
   std::ostringstream out;
-  e.to_str(out, 2);
+  e->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(  Else{
     {
       Discard{}
diff --git a/src/ast/expression_test.cc b/src/ast/expression_test.cc
index bf6bb74..35a381e 100644
--- a/src/ast/expression_test.cc
+++ b/src/ast/expression_test.cc
@@ -22,11 +22,11 @@
 namespace ast {
 namespace {
 
-class Expr : public Expression {
+class FakeExpr : public Expression {
  public:
-  Expr() : Expression(Source{}) {}
+  FakeExpr() : Expression(Source{}) {}
 
-  Expr* Clone(CloneContext*) const override { return nullptr; }
+  FakeExpr* Clone(CloneContext*) const override { return nullptr; }
   bool IsValid() const override { return true; }
   void to_str(std::ostream&, size_t) const override {}
 };
@@ -34,20 +34,17 @@
 using ExpressionTest = TestHelper;
 
 TEST_F(ExpressionTest, set_result_type) {
-  type::I32 i32;
-
-  Expr e;
-  e.set_result_type(&i32);
+  FakeExpr e;
+  e.set_result_type(ty.i32);
   ASSERT_NE(e.result_type(), nullptr);
   EXPECT_TRUE(e.result_type()->Is<type::I32>());
 }
 
 TEST_F(ExpressionTest, set_result_type_alias) {
-  type::I32 i32;
-  type::Alias a(mod.RegisterSymbol("a"), "a", &i32);
-  type::Alias b(mod.RegisterSymbol("b"), "b", &a);
+  type::Alias a(mod->RegisterSymbol("a"), "a", ty.i32);
+  type::Alias b(mod->RegisterSymbol("b"), "b", &a);
 
-  Expr e;
+  FakeExpr e;
   e.set_result_type(&b);
   ASSERT_NE(e.result_type(), nullptr);
   EXPECT_TRUE(e.result_type()->Is<type::I32>());
diff --git a/src/ast/fallthrough_statement_test.cc b/src/ast/fallthrough_statement_test.cc
index 1e926dd..a17131a 100644
--- a/src/ast/fallthrough_statement_test.cc
+++ b/src/ast/fallthrough_statement_test.cc
@@ -23,34 +23,34 @@
 using FallthroughStatementTest = TestHelper;
 
 TEST_F(FallthroughStatementTest, Creation) {
-  FallthroughStatement stmt(Source{});
-  EXPECT_EQ(stmt.source().range.begin.line, 0u);
-  EXPECT_EQ(stmt.source().range.begin.column, 0u);
-  EXPECT_EQ(stmt.source().range.end.line, 0u);
-  EXPECT_EQ(stmt.source().range.end.column, 0u);
+  auto* stmt = create<FallthroughStatement>();
+  EXPECT_EQ(stmt->source().range.begin.line, 0u);
+  EXPECT_EQ(stmt->source().range.begin.column, 0u);
+  EXPECT_EQ(stmt->source().range.end.line, 0u);
+  EXPECT_EQ(stmt->source().range.end.column, 0u);
 }
 
 TEST_F(FallthroughStatementTest, Creation_WithSource) {
-  FallthroughStatement stmt(Source{Source::Location{20, 2}});
-  auto src = stmt.source();
+  auto* stmt = create<FallthroughStatement>(Source{Source::Location{20, 2}});
+  auto src = stmt->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(FallthroughStatementTest, IsFallthrough) {
-  FallthroughStatement stmt(Source{});
-  EXPECT_TRUE(stmt.Is<FallthroughStatement>());
+  auto* stmt = create<FallthroughStatement>();
+  EXPECT_TRUE(stmt->Is<FallthroughStatement>());
 }
 
 TEST_F(FallthroughStatementTest, IsValid) {
-  FallthroughStatement stmt(Source{});
-  EXPECT_TRUE(stmt.IsValid());
+  auto* stmt = create<FallthroughStatement>();
+  EXPECT_TRUE(stmt->IsValid());
 }
 
 TEST_F(FallthroughStatementTest, ToStr) {
-  FallthroughStatement stmt(Source{});
+  auto* stmt = create<FallthroughStatement>();
   std::ostringstream out;
-  stmt.to_str(out, 2);
+  stmt->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(  Fallthrough{}
 )");
 }
diff --git a/src/ast/float_literal_test.cc b/src/ast/float_literal_test.cc
index 2b4394e..1cd4cfe 100644
--- a/src/ast/float_literal_test.cc
+++ b/src/ast/float_literal_test.cc
@@ -28,16 +28,13 @@
 using FloatLiteralTest = TestHelper;
 
 TEST_F(FloatLiteralTest, Value) {
-  type::F32 f32;
-  FloatLiteral f{Source{}, &f32, 47.2f};
-  ASSERT_TRUE(f.Is<FloatLiteral>());
-  EXPECT_EQ(f.value(), 47.2f);
+  auto* f = create<FloatLiteral>(ty.f32, 47.2f);
+  ASSERT_TRUE(f->Is<FloatLiteral>());
+  EXPECT_EQ(f->value(), 47.2f);
 }
 
 TEST_F(FloatLiteralTest, Is) {
-  type::F32 f32;
-  FloatLiteral f{Source{}, &f32, 42.f};
-  Literal* l = &f;
+  ast::Literal* l = create<FloatLiteral>(ty.f32, 42.f);
   EXPECT_FALSE(l->Is<BoolLiteral>());
   EXPECT_FALSE(l->Is<SintLiteral>());
   EXPECT_FALSE(l->Is<IntLiteral>());
@@ -47,16 +44,14 @@
 }
 
 TEST_F(FloatLiteralTest, ToStr) {
-  type::F32 f32;
-  FloatLiteral f{Source{}, &f32, 42.1f};
+  auto* f = create<FloatLiteral>(ty.f32, 42.1f);
 
-  EXPECT_EQ(f.to_str(), "42.099998");
+  EXPECT_EQ(f->to_str(), "42.099998");
 }
 
 TEST_F(FloatLiteralTest, ToName) {
-  type::F32 f32;
-  FloatLiteral f{Source{}, &f32, 42.1f};
-  EXPECT_EQ(f.name(), "__float42.0999985");
+  auto* f = create<FloatLiteral>(ty.f32, 42.1f);
+  EXPECT_EQ(f->name(), "__float42.0999985");
 }
 
 }  // namespace
diff --git a/src/ast/function_test.cc b/src/ast/function_test.cc
index 0d9f645..718a2ef 100644
--- a/src/ast/function_test.cc
+++ b/src/ast/function_test.cc
@@ -19,9 +19,6 @@
 #include "src/ast/location_decoration.h"
 #include "src/ast/pipeline_stage.h"
 #include "src/ast/test_helper.h"
-#include "src/ast/type/f32_type.h"
-#include "src/ast/type/i32_type.h"
-#include "src/ast/type/void_type.h"
 #include "src/ast/variable.h"
 #include "src/ast/workgroup_decoration.h"
 
@@ -32,113 +29,91 @@
 using FunctionTest = TestHelper;
 
 TEST_F(FunctionTest, Creation) {
-  type::Void void_type;
-  type::I32 i32;
-
-  auto func_sym = mod.RegisterSymbol("func");
+  auto func_sym = mod->RegisterSymbol("func");
 
   VariableList params;
-  params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
-                                    false, nullptr,
-                                    ast::VariableDecorationList{}));
+  params.push_back(Var("var", StorageClass::kNone, ty.i32));
   auto* var = params[0];
 
-  Function f(Source{}, func_sym, "func", params, &void_type,
-             create<BlockStatement>(Source{}, StatementList{}),
-             FunctionDecorationList{});
-  EXPECT_EQ(f.symbol(), func_sym);
-  EXPECT_EQ(f.name(), "func");
-  ASSERT_EQ(f.params().size(), 1u);
-  EXPECT_EQ(f.return_type(), &void_type);
-  EXPECT_EQ(f.params()[0], var);
+  auto* f = create<Function>(func_sym, "func", params, ty.void_,
+                             create<BlockStatement>(StatementList{}),
+                             FunctionDecorationList{});
+  EXPECT_EQ(f->symbol(), func_sym);
+  EXPECT_EQ(f->name(), "func");
+  ASSERT_EQ(f->params().size(), 1u);
+  EXPECT_EQ(f->return_type(), ty.void_);
+  EXPECT_EQ(f->params()[0], var);
 }
 
 TEST_F(FunctionTest, Creation_WithSource) {
-  type::Void void_type;
-  type::I32 i32;
-
-  auto func_sym = mod.RegisterSymbol("func");
+  auto func_sym = mod->RegisterSymbol("func");
 
   VariableList params;
-  params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
-                                    false, nullptr,
-                                    ast::VariableDecorationList{}));
+  params.push_back(Var("var", StorageClass::kNone, ty.i32));
 
-  Function f(Source{Source::Location{20, 2}}, func_sym, "func", params,
-             &void_type, create<BlockStatement>(Source{}, StatementList{}),
-             FunctionDecorationList{});
-  auto src = f.source();
+  auto* f = create<Function>(
+      Source{Source::Location{20, 2}}, func_sym, "func", params, ty.void_,
+      create<BlockStatement>(StatementList{}), FunctionDecorationList{});
+  auto src = f->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(FunctionTest, AddDuplicateReferencedVariables) {
-  type::Void void_type;
-  type::I32 i32;
+  auto func_sym = mod->RegisterSymbol("func");
 
-  auto func_sym = mod.RegisterSymbol("func");
+  auto* v = Var("var", StorageClass::kInput, ty.i32);
+  auto* f = create<Function>(func_sym, "func", VariableList{}, ty.void_,
+                             create<BlockStatement>(StatementList{}),
+                             FunctionDecorationList{});
 
-  Variable v(Source{}, "var", StorageClass::kInput, &i32, false, nullptr,
-             ast::VariableDecorationList{});
-  Function f(Source{}, func_sym, "func", VariableList{}, &void_type,
-             create<BlockStatement>(Source{}, StatementList{}),
-             FunctionDecorationList{});
+  f->add_referenced_module_variable(v);
+  ASSERT_EQ(f->referenced_module_variables().size(), 1u);
+  EXPECT_EQ(f->referenced_module_variables()[0], v);
 
-  f.add_referenced_module_variable(&v);
-  ASSERT_EQ(f.referenced_module_variables().size(), 1u);
-  EXPECT_EQ(f.referenced_module_variables()[0], &v);
+  f->add_referenced_module_variable(v);
+  ASSERT_EQ(f->referenced_module_variables().size(), 1u);
 
-  f.add_referenced_module_variable(&v);
-  ASSERT_EQ(f.referenced_module_variables().size(), 1u);
-
-  Variable v2(Source{}, "var2", StorageClass::kOutput, &i32, false, nullptr,
-              ast::VariableDecorationList{});
-  f.add_referenced_module_variable(&v2);
-  ASSERT_EQ(f.referenced_module_variables().size(), 2u);
-  EXPECT_EQ(f.referenced_module_variables()[1], &v2);
+  auto* v2 = Var("var2", StorageClass::kOutput, ty.i32);
+  f->add_referenced_module_variable(v2);
+  ASSERT_EQ(f->referenced_module_variables().size(), 2u);
+  EXPECT_EQ(f->referenced_module_variables()[1], v2);
 }
 
 TEST_F(FunctionTest, GetReferenceLocations) {
-  type::Void void_type;
-  type::I32 i32;
+  auto func_sym = mod->RegisterSymbol("func");
 
-  auto func_sym = mod.RegisterSymbol("func");
+  auto* loc1 = Var("loc1", StorageClass::kInput, ty.i32, nullptr,
+                   ast::VariableDecorationList{
+                       create<LocationDecoration>(0),
+                   });
 
-  auto* loc1 = create<Variable>(Source{}, "loc1", StorageClass::kInput, &i32,
-                                false, nullptr,
-                                ast::VariableDecorationList{
-                                    create<LocationDecoration>(Source{}, 0),
-                                });
+  auto* loc2 = Var("loc2", StorageClass::kInput, ty.i32, nullptr,
+                   ast::VariableDecorationList{
+                       create<LocationDecoration>(1),
+                   });
 
-  auto* loc2 = create<Variable>(Source{}, "loc2", StorageClass::kInput, &i32,
-                                false, nullptr,
-                                ast::VariableDecorationList{
-                                    create<LocationDecoration>(Source{}, 1),
-                                });
+  auto* builtin1 = Var("builtin1", StorageClass::kInput, ty.i32, nullptr,
+                       ast::VariableDecorationList{
+                           create<BuiltinDecoration>(Builtin::kPosition),
+                       });
 
-  auto* builtin1 = create<Variable>(
-      Source{}, "builtin1", StorageClass::kInput, &i32, false, nullptr,
-      ast::VariableDecorationList{
-          create<BuiltinDecoration>(Source{}, Builtin::kPosition),
-      });
+  auto* builtin2 = Var("builtin2", StorageClass::kInput, ty.i32, nullptr,
+                       ast::VariableDecorationList{
+                           create<BuiltinDecoration>(Builtin::kFragDepth),
+                       });
 
-  auto* builtin2 = create<Variable>(
-      Source{}, "builtin2", StorageClass::kInput, &i32, false, nullptr,
-      ast::VariableDecorationList{
-          create<BuiltinDecoration>(Source{}, Builtin::kFragDepth),
-      });
+  auto* f = create<Function>(func_sym, "func", VariableList{}, ty.void_,
+                             create<BlockStatement>(StatementList{}),
+                             FunctionDecorationList{});
 
-  Function f(Source{}, func_sym, "func", VariableList{}, &void_type,
-             create<BlockStatement>(Source{}, StatementList{}),
-             FunctionDecorationList{});
+  f->add_referenced_module_variable(loc1);
+  f->add_referenced_module_variable(builtin1);
+  f->add_referenced_module_variable(loc2);
+  f->add_referenced_module_variable(builtin2);
+  ASSERT_EQ(f->referenced_module_variables().size(), 4u);
 
-  f.add_referenced_module_variable(loc1);
-  f.add_referenced_module_variable(builtin1);
-  f.add_referenced_module_variable(loc2);
-  f.add_referenced_module_variable(builtin2);
-  ASSERT_EQ(f.referenced_module_variables().size(), 4u);
-
-  auto ref_locs = f.referenced_location_variables();
+  auto ref_locs = f->referenced_location_variables();
   ASSERT_EQ(ref_locs.size(), 2u);
   EXPECT_EQ(ref_locs[0].first, loc1);
   EXPECT_EQ(ref_locs[0].second->value(), 0u);
@@ -147,46 +122,39 @@
 }
 
 TEST_F(FunctionTest, GetReferenceBuiltins) {
-  type::Void void_type;
-  type::I32 i32;
+  auto func_sym = mod->RegisterSymbol("func");
 
-  auto func_sym = mod.RegisterSymbol("func");
+  auto* loc1 = Var("loc1", StorageClass::kInput, ty.i32, nullptr,
+                   ast::VariableDecorationList{
+                       create<LocationDecoration>(0),
+                   });
 
-  auto* loc1 = create<Variable>(Source{}, "loc1", StorageClass::kInput, &i32,
-                                false, nullptr,
-                                ast::VariableDecorationList{
-                                    create<LocationDecoration>(Source{}, 0),
-                                });
+  auto* loc2 = Var("loc2", StorageClass::kInput, ty.i32, nullptr,
+                   ast::VariableDecorationList{
+                       create<LocationDecoration>(1),
+                   });
 
-  auto* loc2 = create<Variable>(Source{}, "loc2", StorageClass::kInput, &i32,
-                                false, nullptr,
-                                ast::VariableDecorationList{
-                                    create<LocationDecoration>(Source{}, 1),
-                                });
+  auto* builtin1 = Var("builtin1", StorageClass::kInput, ty.i32, nullptr,
+                       ast::VariableDecorationList{
+                           create<BuiltinDecoration>(Builtin::kPosition),
+                       });
 
-  auto* builtin1 = create<Variable>(
-      Source{}, "builtin1", StorageClass::kInput, &i32, false, nullptr,
-      ast::VariableDecorationList{
-          create<BuiltinDecoration>(Source{}, Builtin::kPosition),
-      });
+  auto* builtin2 = Var("builtin2", StorageClass::kInput, ty.i32, nullptr,
+                       ast::VariableDecorationList{
+                           create<BuiltinDecoration>(Builtin::kFragDepth),
+                       });
 
-  auto* builtin2 = create<Variable>(
-      Source{}, "builtin2", StorageClass::kInput, &i32, false, nullptr,
-      ast::VariableDecorationList{
-          create<BuiltinDecoration>(Source{}, Builtin::kFragDepth),
-      });
+  auto* f = create<Function>(func_sym, "func", VariableList{}, ty.void_,
+                             create<BlockStatement>(StatementList{}),
+                             FunctionDecorationList{});
 
-  Function f(Source{}, func_sym, "func", VariableList{}, &void_type,
-             create<BlockStatement>(Source{}, StatementList{}),
-             FunctionDecorationList{});
+  f->add_referenced_module_variable(loc1);
+  f->add_referenced_module_variable(builtin1);
+  f->add_referenced_module_variable(loc2);
+  f->add_referenced_module_variable(builtin2);
+  ASSERT_EQ(f->referenced_module_variables().size(), 4u);
 
-  f.add_referenced_module_variable(loc1);
-  f.add_referenced_module_variable(builtin1);
-  f.add_referenced_module_variable(loc2);
-  f.add_referenced_module_variable(builtin2);
-  ASSERT_EQ(f.referenced_module_variables().size(), 4u);
-
-  auto ref_locs = f.referenced_builtin_variables();
+  auto ref_locs = f->referenced_builtin_variables();
   ASSERT_EQ(ref_locs.size(), 2u);
   EXPECT_EQ(ref_locs[0].first, builtin1);
   EXPECT_EQ(ref_locs[0].second->value(), Builtin::kPosition);
@@ -195,173 +163,131 @@
 }
 
 TEST_F(FunctionTest, AddDuplicateEntryPoints) {
-  type::Void void_type;
+  auto func_sym = mod->RegisterSymbol("func");
+  auto main_sym = mod->RegisterSymbol("main");
 
-  auto func_sym = mod.RegisterSymbol("func");
-  auto main_sym = mod.RegisterSymbol("main");
+  auto* f = create<Function>(func_sym, "func", VariableList{}, ty.void_,
+                             create<BlockStatement>(StatementList{}),
+                             FunctionDecorationList{});
 
-  Function f(Source{}, func_sym, "func", VariableList{}, &void_type,
-             create<BlockStatement>(Source{}, StatementList{}),
-             FunctionDecorationList{});
+  f->add_ancestor_entry_point(main_sym);
+  ASSERT_EQ(1u, f->ancestor_entry_points().size());
+  EXPECT_EQ(main_sym, f->ancestor_entry_points()[0]);
 
-  f.add_ancestor_entry_point(main_sym);
-  ASSERT_EQ(1u, f.ancestor_entry_points().size());
-  EXPECT_EQ(main_sym, f.ancestor_entry_points()[0]);
-
-  f.add_ancestor_entry_point(main_sym);
-  ASSERT_EQ(1u, f.ancestor_entry_points().size());
-  EXPECT_EQ(main_sym, f.ancestor_entry_points()[0]);
+  f->add_ancestor_entry_point(main_sym);
+  ASSERT_EQ(1u, f->ancestor_entry_points().size());
+  EXPECT_EQ(main_sym, f->ancestor_entry_points()[0]);
 }
 
 TEST_F(FunctionTest, IsValid) {
-  type::Void void_type;
-  type::I32 i32;
-
-  auto func_sym = mod.RegisterSymbol("func");
+  auto func_sym = mod->RegisterSymbol("func");
 
   VariableList params;
-  params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
-                                    false, nullptr,
-                                    ast::VariableDecorationList{}));
+  params.push_back(Var("var", StorageClass::kNone, ty.i32));
 
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                       });
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+  });
 
-  Function f(Source{}, func_sym, "func", params, &void_type, body,
-             FunctionDecorationList{});
-  EXPECT_TRUE(f.IsValid());
+  auto* f = create<Function>(func_sym, "func", params, ty.void_, body,
+                             FunctionDecorationList{});
+  EXPECT_TRUE(f->IsValid());
 }
 
 TEST_F(FunctionTest, IsValid_InvalidName) {
-  type::Void void_type;
-  type::I32 i32;
-
-  auto func_sym = mod.RegisterSymbol("");
+  auto func_sym = mod->RegisterSymbol("");
 
   VariableList params;
-  params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
-                                    false, nullptr,
-                                    ast::VariableDecorationList{}));
+  params.push_back(Var("var", StorageClass::kNone, ty.i32));
 
-  Function f(Source{}, func_sym, "", params, &void_type,
-             create<BlockStatement>(Source{}, StatementList{}),
-             FunctionDecorationList{});
-  EXPECT_FALSE(f.IsValid());
+  auto* f = create<Function>(func_sym, "", params, ty.void_,
+                             create<BlockStatement>(StatementList{}),
+                             FunctionDecorationList{});
+  EXPECT_FALSE(f->IsValid());
 }
 
 TEST_F(FunctionTest, IsValid_MissingReturnType) {
-  type::I32 i32;
-
-  auto func_sym = mod.RegisterSymbol("func");
+  auto func_sym = mod->RegisterSymbol("func");
 
   VariableList params;
-  params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
-                                    false, nullptr,
-                                    ast::VariableDecorationList{}));
+  params.push_back(Var("var", StorageClass::kNone, ty.i32));
 
-  Function f(Source{}, func_sym, "func", params, nullptr,
-             create<BlockStatement>(Source{}, StatementList{}),
-             FunctionDecorationList{});
-  EXPECT_FALSE(f.IsValid());
+  auto* f = create<Function>(func_sym, "func", params, nullptr,
+                             create<BlockStatement>(StatementList{}),
+                             FunctionDecorationList{});
+  EXPECT_FALSE(f->IsValid());
 }
 
 TEST_F(FunctionTest, IsValid_NullParam) {
-  type::Void void_type;
-  type::I32 i32;
-
-  auto func_sym = mod.RegisterSymbol("func");
+  auto func_sym = mod->RegisterSymbol("func");
 
   VariableList params;
-  params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
-                                    false, nullptr,
-                                    ast::VariableDecorationList{}));
+  params.push_back(Var("var", StorageClass::kNone, ty.i32));
   params.push_back(nullptr);
 
-  Function f(Source{}, func_sym, "func", params, &void_type,
-             create<BlockStatement>(Source{}, StatementList{}),
-             FunctionDecorationList{});
-  EXPECT_FALSE(f.IsValid());
+  auto* f = create<Function>(func_sym, "func", params, ty.void_,
+                             create<BlockStatement>(StatementList{}),
+                             FunctionDecorationList{});
+  EXPECT_FALSE(f->IsValid());
 }
 
 TEST_F(FunctionTest, IsValid_InvalidParam) {
-  type::Void void_type;
-
-  auto func_sym = mod.RegisterSymbol("func");
+  auto func_sym = mod->RegisterSymbol("func");
 
   VariableList params;
-  params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone,
-                                    nullptr, false, nullptr,
-                                    ast::VariableDecorationList{}));
+  params.push_back(Var("var", StorageClass::kNone, nullptr));
 
-  Function f(Source{}, func_sym, "func", params, &void_type,
-             create<BlockStatement>(Source{}, StatementList{}),
-             FunctionDecorationList{});
-  EXPECT_FALSE(f.IsValid());
+  auto* f = create<Function>(func_sym, "func", params, ty.void_,
+                             create<BlockStatement>(StatementList{}),
+                             FunctionDecorationList{});
+  EXPECT_FALSE(f->IsValid());
 }
 
 TEST_F(FunctionTest, IsValid_NullBodyStatement) {
-  type::Void void_type;
-  type::I32 i32;
-
-  auto func_sym = mod.RegisterSymbol("func");
+  auto func_sym = mod->RegisterSymbol("func");
 
   VariableList params;
-  params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
-                                    false, nullptr,
-                                    ast::VariableDecorationList{}));
+  params.push_back(Var("var", StorageClass::kNone, ty.i32));
 
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                           nullptr,
-                                       });
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+      nullptr,
+  });
 
-  Function f(Source{}, func_sym, "func", params, &void_type, body,
-             FunctionDecorationList{});
+  auto* f = create<Function>(func_sym, "func", params, ty.void_, body,
+                             FunctionDecorationList{});
 
-  EXPECT_FALSE(f.IsValid());
+  EXPECT_FALSE(f->IsValid());
 }
 
 TEST_F(FunctionTest, IsValid_InvalidBodyStatement) {
-  type::Void void_type;
-  type::I32 i32;
-
-  auto func_sym = mod.RegisterSymbol("func");
+  auto func_sym = mod->RegisterSymbol("func");
 
   VariableList params;
-  params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
-                                    false, nullptr,
-                                    ast::VariableDecorationList{}));
+  params.push_back(Var("var", StorageClass::kNone, ty.i32));
 
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                           nullptr,
-                                       });
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+      nullptr,
+  });
 
-  Function f(Source{}, func_sym, "func", params, &void_type, body,
-             FunctionDecorationList{});
-  EXPECT_FALSE(f.IsValid());
+  auto* f = create<Function>(func_sym, "func", params, ty.void_, body,
+                             FunctionDecorationList{});
+  EXPECT_FALSE(f->IsValid());
 }
 
 TEST_F(FunctionTest, ToStr) {
-  type::Void void_type;
-  type::I32 i32;
+  auto func_sym = mod->RegisterSymbol("func");
 
-  auto func_sym = mod.RegisterSymbol("func");
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+  });
 
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                       });
-
-  Function f(Source{}, func_sym, "func", {}, &void_type, body,
-             FunctionDecorationList{});
+  auto* f = create<Function>(func_sym, "func", VariableList{}, ty.void_, body,
+                             FunctionDecorationList{});
 
   std::ostringstream out;
-  f.to_str(out, 2);
+  f->to_str(out, 2);
   EXPECT_EQ(demangle(out.str()), R"(  Function func -> __void
   ()
   {
@@ -371,21 +297,17 @@
 }
 
 TEST_F(FunctionTest, ToStr_WithDecoration) {
-  type::Void void_type;
-  type::I32 i32;
+  auto func_sym = mod->RegisterSymbol("func");
 
-  auto func_sym = mod.RegisterSymbol("func");
-
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                       });
-  Function f(
-      Source{}, func_sym, "func", {}, &void_type, body,
-      FunctionDecorationList{create<WorkgroupDecoration>(Source{}, 2, 4, 6)});
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+  });
+  auto* f = create<Function>(
+      func_sym, "func", VariableList{}, ty.void_, body,
+      FunctionDecorationList{create<WorkgroupDecoration>(2, 4, 6)});
 
   std::ostringstream out;
-  f.to_str(out, 2);
+  f->to_str(out, 2);
   EXPECT_EQ(demangle(out.str()), R"(  Function func -> __void
   WorkgroupDecoration{2 4 6}
   ()
@@ -396,25 +318,19 @@
 }
 
 TEST_F(FunctionTest, ToStr_WithParams) {
-  type::Void void_type;
-  type::I32 i32;
-
-  auto func_sym = mod.RegisterSymbol("func");
+  auto func_sym = mod->RegisterSymbol("func");
 
   VariableList params;
-  params.push_back(create<Variable>(Source{}, "var", StorageClass::kNone, &i32,
-                                    false, nullptr,
-                                    ast::VariableDecorationList{}));
+  params.push_back(Var("var", StorageClass::kNone, ty.i32));
 
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                       });
-  Function f(Source{}, func_sym, "func", params, &void_type, body,
-             FunctionDecorationList{});
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+  });
+  auto* f = create<Function>(func_sym, "func", params, ty.void_, body,
+                             FunctionDecorationList{});
 
   std::ostringstream out;
-  f.to_str(out, 2);
+  f->to_str(out, 2);
   EXPECT_EQ(demangle(out.str()), R"(  Function func -> __void
   (
     Variable{
@@ -430,94 +346,77 @@
 }
 
 TEST_F(FunctionTest, TypeName) {
-  type::Void void_type;
+  auto func_sym = mod->RegisterSymbol("func");
 
-  auto func_sym = mod.RegisterSymbol("func");
-
-  Function f(Source{}, func_sym, "func", {}, &void_type,
-             create<BlockStatement>(Source{}, StatementList{}),
-             FunctionDecorationList{});
-  EXPECT_EQ(f.type_name(), "__func__void");
+  auto* f = create<Function>(func_sym, "func", VariableList{}, ty.void_,
+                             create<BlockStatement>(StatementList{}),
+                             FunctionDecorationList{});
+  EXPECT_EQ(f->type_name(), "__func__void");
 }
 
 TEST_F(FunctionTest, TypeName_WithParams) {
-  type::Void void_type;
-  type::I32 i32;
-  type::F32 f32;
-
-  auto func_sym = mod.RegisterSymbol("func");
+  auto func_sym = mod->RegisterSymbol("func");
 
   VariableList params;
-  params.push_back(create<Variable>(Source{}, "var1", StorageClass::kNone, &i32,
-                                    false, nullptr,
-                                    ast::VariableDecorationList{}));
-  params.push_back(create<Variable>(Source{}, "var2", StorageClass::kNone, &f32,
-                                    false, nullptr,
-                                    ast::VariableDecorationList{}));
+  params.push_back(Var("var1", StorageClass::kNone, ty.i32));
+  params.push_back(Var("var2", StorageClass::kNone, ty.f32));
 
-  Function f(Source{}, func_sym, "func", params, &void_type,
-             create<BlockStatement>(Source{}, StatementList{}),
-             FunctionDecorationList{});
-  EXPECT_EQ(f.type_name(), "__func__void__i32__f32");
+  auto* f = create<Function>(func_sym, "func", params, ty.void_,
+                             create<BlockStatement>(StatementList{}),
+                             FunctionDecorationList{});
+  EXPECT_EQ(f->type_name(), "__func__void__i32__f32");
 }
 
 TEST_F(FunctionTest, GetLastStatement) {
-  type::Void void_type;
-
-  auto func_sym = mod.RegisterSymbol("func");
+  auto func_sym = mod->RegisterSymbol("func");
 
   VariableList params;
-  auto* stmt = create<DiscardStatement>(Source{});
-  auto* body = create<BlockStatement>(Source{}, StatementList{stmt});
-  Function f(Source{}, func_sym, "func", params, &void_type, body,
-             FunctionDecorationList{});
+  auto* stmt = create<DiscardStatement>();
+  auto* body = create<BlockStatement>(StatementList{stmt});
+  auto* f = create<Function>(func_sym, "func", params, ty.void_, body,
+                             FunctionDecorationList{});
 
-  EXPECT_EQ(f.get_last_statement(), stmt);
+  EXPECT_EQ(f->get_last_statement(), stmt);
 }
 
 TEST_F(FunctionTest, GetLastStatement_nullptr) {
-  type::Void void_type;
-
-  auto func_sym = mod.RegisterSymbol("func");
+  auto func_sym = mod->RegisterSymbol("func");
 
   VariableList params;
-  auto* body = create<BlockStatement>(Source{}, StatementList{});
-  Function f(Source{}, func_sym, "func", params, &void_type, body,
-             FunctionDecorationList{});
+  auto* body = create<BlockStatement>(StatementList{});
+  auto* f = create<Function>(func_sym, "func", params, ty.void_, body,
+                             FunctionDecorationList{});
 
-  EXPECT_EQ(f.get_last_statement(), nullptr);
+  EXPECT_EQ(f->get_last_statement(), nullptr);
 }
 
 TEST_F(FunctionTest, WorkgroupSize_NoneSet) {
-  type::Void void_type;
+  auto func_sym = mod->RegisterSymbol("func");
 
-  auto func_sym = mod.RegisterSymbol("func");
-
-  Function f(Source{}, func_sym, "func", {}, &void_type,
-             create<BlockStatement>(Source{}, StatementList{}),
-             FunctionDecorationList{});
+  auto* f = create<Function>(func_sym, "func", VariableList{}, ty.void_,
+                             create<BlockStatement>(StatementList{}),
+                             FunctionDecorationList{});
   uint32_t x = 0;
   uint32_t y = 0;
   uint32_t z = 0;
-  std::tie(x, y, z) = f.workgroup_size();
+  std::tie(x, y, z) = f->workgroup_size();
   EXPECT_EQ(x, 1u);
   EXPECT_EQ(y, 1u);
   EXPECT_EQ(z, 1u);
 }
 
 TEST_F(FunctionTest, WorkgroupSize) {
-  type::Void void_type;
+  auto func_sym = mod->RegisterSymbol("func");
 
-  auto func_sym = mod.RegisterSymbol("func");
-
-  Function f(Source{}, func_sym, "func", {}, &void_type,
-             create<BlockStatement>(Source{}, StatementList{}),
-             {create<WorkgroupDecoration>(Source{}, 2u, 4u, 6u)});
+  auto* f = create<Function>(
+      func_sym, "func", VariableList{}, ty.void_,
+      create<BlockStatement>(StatementList{}),
+      FunctionDecorationList{create<WorkgroupDecoration>(2u, 4u, 6u)});
 
   uint32_t x = 0;
   uint32_t y = 0;
   uint32_t z = 0;
-  std::tie(x, y, z) = f.workgroup_size();
+  std::tie(x, y, z) = f->workgroup_size();
   EXPECT_EQ(x, 2u);
   EXPECT_EQ(y, 4u);
   EXPECT_EQ(z, 6u);
diff --git a/src/ast/identifier_expression_test.cc b/src/ast/identifier_expression_test.cc
index 70a03bb..92b30d3 100644
--- a/src/ast/identifier_expression_test.cc
+++ b/src/ast/identifier_expression_test.cc
@@ -23,36 +23,36 @@
 using IdentifierExpressionTest = TestHelper;
 
 TEST_F(IdentifierExpressionTest, Creation) {
-  IdentifierExpression i(Source{}, mod.RegisterSymbol("ident"), "ident");
-  EXPECT_EQ(i.symbol(), Symbol(1));
-  EXPECT_EQ(i.name(), "ident");
+  auto* i = Expr("ident");
+  EXPECT_EQ(i->symbol(), Symbol(1));
+  EXPECT_EQ(i->name(), "ident");
 }
 
 TEST_F(IdentifierExpressionTest, Creation_WithSource) {
-  IdentifierExpression i(Source{Source::Location{20, 2}},
-                         mod.RegisterSymbol("ident"), "ident");
-  EXPECT_EQ(i.symbol(), Symbol(1));
-  EXPECT_EQ(i.name(), "ident");
+  auto* i = create<IdentifierExpression>(Source{Source::Location{20, 2}},
+                                         mod->RegisterSymbol("ident"), "ident");
+  EXPECT_EQ(i->symbol(), Symbol(1));
+  EXPECT_EQ(i->name(), "ident");
 
-  auto src = i.source();
+  auto src = i->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(IdentifierExpressionTest, IsIdentifier) {
-  IdentifierExpression i(Source{}, mod.RegisterSymbol("ident"), "ident");
-  EXPECT_TRUE(i.Is<IdentifierExpression>());
+  auto* i = Expr("ident");
+  EXPECT_TRUE(i->Is<IdentifierExpression>());
 }
 
 TEST_F(IdentifierExpressionTest, IsValid) {
-  IdentifierExpression i(Source{}, mod.RegisterSymbol("ident"), "ident");
-  EXPECT_TRUE(i.IsValid());
+  auto* i = Expr("ident");
+  EXPECT_TRUE(i->IsValid());
 }
 
 TEST_F(IdentifierExpressionTest, ToStr) {
-  IdentifierExpression i(Source{}, mod.RegisterSymbol("ident"), "ident");
+  auto* i = Expr("ident");
   std::ostringstream out;
-  i.to_str(out, 2);
+  i->to_str(out, 2);
   EXPECT_EQ(demangle(out.str()), R"(  Identifier[not set]{ident}
 )");
 }
diff --git a/src/ast/if_statement_test.cc b/src/ast/if_statement_test.cc
index 250c145..ba3e6f7 100644
--- a/src/ast/if_statement_test.cc
+++ b/src/ast/if_statement_test.cc
@@ -25,176 +25,153 @@
 using IfStatementTest = TestHelper;
 
 TEST_F(IfStatementTest, Creation) {
-  auto* cond = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("cond"), "cond");
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
-  IfStatement stmt(Source{Source::Location{20, 2}}, cond, body,
-                   ElseStatementList{});
-  auto src = stmt.source();
+  auto* cond = Expr("cond");
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
+  auto* stmt = create<IfStatement>(Source{Source::Location{20, 2}}, cond, body,
+                                   ElseStatementList{});
+  auto src = stmt->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(IfStatementTest, IsIf) {
-  IfStatement stmt(Source{}, nullptr,
-                   create<BlockStatement>(Source{}, StatementList{}),
-                   ElseStatementList{});
-  EXPECT_TRUE(stmt.Is<IfStatement>());
+  auto* stmt = create<IfStatement>(
+      nullptr, create<BlockStatement>(StatementList{}), ElseStatementList{});
+  EXPECT_TRUE(stmt->Is<IfStatement>());
 }
 
 TEST_F(IfStatementTest, IsValid) {
-  auto* cond = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("cond"), "cond");
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
-  IfStatement stmt(Source{}, cond, body, ElseStatementList{});
-  EXPECT_TRUE(stmt.IsValid());
+  auto* cond = Expr("cond");
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
+  auto* stmt = create<IfStatement>(cond, body, ElseStatementList{});
+  EXPECT_TRUE(stmt->IsValid());
 }
 
 TEST_F(IfStatementTest, IsValid_WithElseStatements) {
-  auto* cond = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("cond"), "cond");
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
-  IfStatement stmt(Source{}, cond, body,
-                   {
-                       create<ElseStatement>(
-                           Source{},
-                           create<IdentifierExpression>(
-                               Source{}, mod.RegisterSymbol("Ident"), "Ident"),
-                           create<BlockStatement>(Source{}, StatementList{})),
-                       create<ElseStatement>(
-                           Source{}, nullptr,
-                           create<BlockStatement>(Source{}, StatementList{})),
-                   });
-  EXPECT_TRUE(stmt.IsValid());
+  auto* cond = Expr("cond");
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
+  auto* stmt = create<IfStatement>(
+      cond, body,
+      ElseStatementList{
+          create<ElseStatement>(create<IdentifierExpression>(
+                                    mod->RegisterSymbol("Ident"), "Ident"),
+                                create<BlockStatement>(StatementList{})),
+          create<ElseStatement>(nullptr,
+                                create<BlockStatement>(StatementList{})),
+      });
+  EXPECT_TRUE(stmt->IsValid());
 }
 
 TEST_F(IfStatementTest, IsValid_MissingCondition) {
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
-  IfStatement stmt(Source{}, nullptr, body, ElseStatementList{});
-  EXPECT_FALSE(stmt.IsValid());
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
+  auto* stmt = create<IfStatement>(nullptr, body, ElseStatementList{});
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(IfStatementTest, IsValid_InvalidCondition) {
-  auto* cond =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol(""), "");
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
-  IfStatement stmt(Source{}, cond, body, ElseStatementList{});
-  EXPECT_FALSE(stmt.IsValid());
+  auto* cond = Expr("");
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
+  auto* stmt = create<IfStatement>(cond, body, ElseStatementList{});
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(IfStatementTest, IsValid_NullBodyStatement) {
-  auto* cond = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("cond"), "cond");
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                           nullptr,
-                                       });
-  IfStatement stmt(Source{}, cond, body, ElseStatementList{});
-  EXPECT_FALSE(stmt.IsValid());
+  auto* cond = Expr("cond");
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+      nullptr,
+  });
+  auto* stmt = create<IfStatement>(cond, body, ElseStatementList{});
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(IfStatementTest, IsValid_InvalidBodyStatement) {
-  auto* cond = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("cond"), "cond");
+  auto* cond = Expr("cond");
   auto* body = create<BlockStatement>(
-      Source{},
+
       StatementList{
-          create<DiscardStatement>(Source{}),
-          create<IfStatement>(Source{}, nullptr,
-                              create<BlockStatement>(Source{}, StatementList{}),
+          create<DiscardStatement>(),
+          create<IfStatement>(nullptr, create<BlockStatement>(StatementList{}),
                               ast::ElseStatementList{}),
       });
-  IfStatement stmt(Source{}, cond, body, ElseStatementList{});
-  EXPECT_FALSE(stmt.IsValid());
+  auto* stmt = create<IfStatement>(cond, body, ElseStatementList{});
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(IfStatementTest, IsValid_NullElseStatement) {
-  auto* cond = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("cond"), "cond");
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
-  IfStatement stmt(Source{}, cond, body,
-                   {
-                       create<ElseStatement>(
-                           Source{},
-                           create<IdentifierExpression>(
-                               Source{}, mod.RegisterSymbol("Ident"), "Ident"),
-                           create<BlockStatement>(Source{}, StatementList{})),
-                       create<ElseStatement>(
-                           Source{}, nullptr,
-                           create<BlockStatement>(Source{}, StatementList{})),
-                       nullptr,
-                   });
-  EXPECT_FALSE(stmt.IsValid());
+  auto* cond = Expr("cond");
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
+  auto* stmt = create<IfStatement>(
+      cond, body,
+      ElseStatementList{
+          create<ElseStatement>(create<IdentifierExpression>(
+                                    mod->RegisterSymbol("Ident"), "Ident"),
+                                create<BlockStatement>(StatementList{})),
+          create<ElseStatement>(nullptr,
+                                create<BlockStatement>(StatementList{})),
+          nullptr,
+      });
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(IfStatementTest, IsValid_InvalidElseStatement) {
-  auto* cond = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("cond"), "cond");
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
-  IfStatement stmt(Source{}, cond, body,
-                   {
-                       create<ElseStatement>(
-                           Source{},
-                           create<IdentifierExpression>(
-                               Source{}, mod.RegisterSymbol(""), ""),
-                           create<BlockStatement>(Source{}, StatementList{})),
-                   });
-  EXPECT_FALSE(stmt.IsValid());
+  auto* cond = Expr("cond");
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
+  auto* stmt = create<IfStatement>(
+      cond, body,
+      ElseStatementList{
+          create<ElseStatement>(Expr(""),
+                                create<BlockStatement>(StatementList{})),
+      });
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(IfStatementTest, IsValid_MultipleElseWiththoutCondition) {
-  auto* cond = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("cond"), "cond");
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
-  IfStatement stmt(Source{}, cond, body,
-                   {
-                       create<ElseStatement>(
-                           Source{}, nullptr,
-                           create<BlockStatement>(Source{}, StatementList{})),
-                       create<ElseStatement>(
-                           Source{}, nullptr,
-                           create<BlockStatement>(Source{}, StatementList{})),
-                   });
-  EXPECT_FALSE(stmt.IsValid());
+  auto* cond = Expr("cond");
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
+  auto* stmt = create<IfStatement>(
+      cond, body,
+      ElseStatementList{
+          create<ElseStatement>(nullptr,
+                                create<BlockStatement>(StatementList{})),
+          create<ElseStatement>(nullptr,
+                                create<BlockStatement>(StatementList{})),
+      });
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(IfStatementTest, IsValid_ElseNotLast) {
-  auto* cond = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("cond"), "cond");
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
-  IfStatement stmt(Source{}, cond, body,
-                   {
-                       create<ElseStatement>(
-                           Source{}, nullptr,
-                           create<BlockStatement>(Source{}, StatementList{})),
-                       create<ElseStatement>(
-                           Source{},
-                           create<IdentifierExpression>(
-                               Source{}, mod.RegisterSymbol("Ident"), "Ident"),
-                           create<BlockStatement>(Source{}, StatementList{})),
-                   });
-  EXPECT_FALSE(stmt.IsValid());
+  auto* cond = Expr("cond");
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
+  auto* stmt = create<IfStatement>(
+      cond, body,
+      ElseStatementList{
+          create<ElseStatement>(nullptr,
+                                create<BlockStatement>(StatementList{})),
+          create<ElseStatement>(create<IdentifierExpression>(
+                                    mod->RegisterSymbol("Ident"), "Ident"),
+                                create<BlockStatement>(StatementList{})),
+      });
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(IfStatementTest, ToStr) {
-  auto* cond = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("cond"), "cond");
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
-  IfStatement stmt(Source{}, cond, body, ElseStatementList{});
+  auto* cond = Expr("cond");
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
+  auto* stmt = create<IfStatement>(cond, body, ElseStatementList{});
 
   std::ostringstream out;
-  stmt.to_str(out, 2);
+  stmt->to_str(out, 2);
   EXPECT_EQ(demangle(out.str()), R"(  If{
     (
       Identifier[not set]{cond}
@@ -207,27 +184,24 @@
 }
 
 TEST_F(IfStatementTest, ToStr_WithElseStatements) {
-  auto* cond = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("cond"), "cond");
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
-  auto* else_if_body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* cond = Expr("cond");
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
+  auto* else_if_body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
   auto* else_body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{}),
-                              create<DiscardStatement>(Source{})});
-  IfStatement stmt(Source{}, cond, body,
-                   {
-                       create<ElseStatement>(
-                           Source{},
-                           create<IdentifierExpression>(
-                               Source{}, mod.RegisterSymbol("ident"), "ident"),
-                           else_if_body),
-                       create<ElseStatement>(Source{}, nullptr, else_body),
-                   });
+      StatementList{create<DiscardStatement>(), create<DiscardStatement>()});
+  auto* stmt = create<IfStatement>(
+      cond, body,
+      ElseStatementList{
+          create<ElseStatement>(create<IdentifierExpression>(
+                                    mod->RegisterSymbol("ident"), "ident"),
+                                else_if_body),
+          create<ElseStatement>(nullptr, else_body),
+      });
 
   std::ostringstream out;
-  stmt.to_str(out, 2);
+  stmt->to_str(out, 2);
   EXPECT_EQ(demangle(out.str()), R"(  If{
     (
       Identifier[not set]{cond}
diff --git a/src/ast/int_literal_test.cc b/src/ast/int_literal_test.cc
index edf7440..dfeb534 100644
--- a/src/ast/int_literal_test.cc
+++ b/src/ast/int_literal_test.cc
@@ -30,15 +30,13 @@
 using IntLiteralTest = TestHelper;
 
 TEST_F(IntLiteralTest, Sint_IsInt) {
-  type::I32 i32;
-  SintLiteral i{Source{}, &i32, 47};
-  ASSERT_TRUE(i.Is<IntLiteral>());
+  auto* i = create<SintLiteral>(ty.i32, 47);
+  ASSERT_TRUE(i->Is<IntLiteral>());
 }
 
 TEST_F(IntLiteralTest, Uint_IsInt) {
-  type::I32 i32;
-  UintLiteral i{Source{}, &i32, 42};
-  EXPECT_TRUE(i.Is<IntLiteral>());
+  auto* i = create<UintLiteral>(ty.i32, 42);
+  EXPECT_TRUE(i->Is<IntLiteral>());
 }
 
 }  // namespace
diff --git a/src/ast/location_decoration_test.cc b/src/ast/location_decoration_test.cc
index 0e32216..fef2647 100644
--- a/src/ast/location_decoration_test.cc
+++ b/src/ast/location_decoration_test.cc
@@ -26,13 +26,12 @@
 using LocationDecorationTest = TestHelper;
 
 TEST_F(LocationDecorationTest, Creation) {
-  LocationDecoration d{Source{}, 2};
-  EXPECT_EQ(2u, d.value());
+  auto* d = create<LocationDecoration>(2);
+  EXPECT_EQ(2u, d->value());
 }
 
 TEST_F(LocationDecorationTest, Is) {
-  LocationDecoration ld{Source{}, 2};
-  Decoration* d = &ld;
+  Decoration* d = create<LocationDecoration>(2);
   EXPECT_FALSE(d->Is<BindingDecoration>());
   EXPECT_FALSE(d->Is<BuiltinDecoration>());
   EXPECT_FALSE(d->Is<ConstantIdDecoration>());
@@ -41,9 +40,9 @@
 }
 
 TEST_F(LocationDecorationTest, ToStr) {
-  LocationDecoration d{Source{}, 2};
+  auto* d = create<LocationDecoration>(2);
   std::ostringstream out;
-  d.to_str(out, 0);
+  d->to_str(out, 0);
   EXPECT_EQ(out.str(), R"(LocationDecoration{2}
 )");
 }
diff --git a/src/ast/loop_statement_test.cc b/src/ast/loop_statement_test.cc
index 58e4b79..d3dca64 100644
--- a/src/ast/loop_statement_test.cc
+++ b/src/ast/loop_statement_test.cc
@@ -28,153 +28,150 @@
 using LoopStatementTest = TestHelper;
 
 TEST_F(LoopStatementTest, Creation) {
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
   auto* b = body->last();
 
-  auto* continuing = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* continuing =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
 
-  LoopStatement l(Source{}, body, continuing);
-  ASSERT_EQ(l.body()->size(), 1u);
-  EXPECT_EQ(l.body()->get(0), b);
-  ASSERT_EQ(l.continuing()->size(), 1u);
-  EXPECT_EQ(l.continuing()->get(0), continuing->last());
+  auto* l = create<LoopStatement>(body, continuing);
+  ASSERT_EQ(l->body()->size(), 1u);
+  EXPECT_EQ(l->body()->get(0), b);
+  ASSERT_EQ(l->continuing()->size(), 1u);
+  EXPECT_EQ(l->continuing()->get(0), continuing->last());
 }
 
 TEST_F(LoopStatementTest, Creation_WithSource) {
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
 
-  auto* continuing = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* continuing =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
 
-  LoopStatement l(Source{Source::Location{20, 2}}, body, continuing);
-  auto src = l.source();
+  auto* l =
+      create<LoopStatement>(Source{Source::Location{20, 2}}, body, continuing);
+  auto src = l->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(LoopStatementTest, IsLoop) {
-  LoopStatement l(Source{}, create<BlockStatement>(Source{}, StatementList{}),
-                  create<BlockStatement>(Source{}, StatementList{}));
-  EXPECT_TRUE(l.Is<LoopStatement>());
+  auto* l = create<LoopStatement>(create<BlockStatement>(StatementList{}),
+                                  create<BlockStatement>(StatementList{}));
+  EXPECT_TRUE(l->Is<LoopStatement>());
 }
 
 TEST_F(LoopStatementTest, HasContinuing_WithoutContinuing) {
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
 
-  LoopStatement l(Source{}, body, {});
-  EXPECT_FALSE(l.has_continuing());
+  auto* l = create<LoopStatement>(body, nullptr);
+  EXPECT_FALSE(l->has_continuing());
 }
 
 TEST_F(LoopStatementTest, HasContinuing_WithContinuing) {
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
 
-  auto* continuing = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* continuing =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
 
-  LoopStatement l(Source{}, body, continuing);
-  EXPECT_TRUE(l.has_continuing());
+  auto* l = create<LoopStatement>(body, continuing);
+  EXPECT_TRUE(l->has_continuing());
 }
 
 TEST_F(LoopStatementTest, IsValid) {
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
 
-  auto* continuing = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* continuing =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
 
-  LoopStatement l(Source{}, body, continuing);
-  EXPECT_TRUE(l.IsValid());
+  auto* l = create<LoopStatement>(body, continuing);
+  EXPECT_TRUE(l->IsValid());
 }
 
 TEST_F(LoopStatementTest, IsValid_WithoutContinuing) {
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
 
-  LoopStatement l(Source{}, body,
-                  create<BlockStatement>(Source{}, StatementList{}));
-  EXPECT_TRUE(l.IsValid());
+  auto* l =
+      create<LoopStatement>(body, create<BlockStatement>(StatementList{}));
+  EXPECT_TRUE(l->IsValid());
 }
 
 TEST_F(LoopStatementTest, IsValid_WithoutBody) {
-  LoopStatement l(Source{}, create<BlockStatement>(Source{}, StatementList{}),
-                  create<BlockStatement>(Source{}, StatementList{}));
-  EXPECT_TRUE(l.IsValid());
+  auto* l = create<LoopStatement>(create<BlockStatement>(StatementList{}),
+                                  create<BlockStatement>(StatementList{}));
+  EXPECT_TRUE(l->IsValid());
 }
 
 TEST_F(LoopStatementTest, IsValid_NullBodyStatement) {
-  auto* body =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                           nullptr,
-                                       });
+  auto* body = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+      nullptr,
+  });
 
-  auto* continuing = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* continuing =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
 
-  LoopStatement l(Source{}, body, continuing);
-  EXPECT_FALSE(l.IsValid());
+  auto* l = create<LoopStatement>(body, continuing);
+  EXPECT_FALSE(l->IsValid());
 }
 
 TEST_F(LoopStatementTest, IsValid_InvalidBodyStatement) {
   auto* body = create<BlockStatement>(
-      Source{},
+
       StatementList{
-          create<DiscardStatement>(Source{}),
-          create<IfStatement>(Source{}, nullptr,
-                              create<BlockStatement>(Source{}, StatementList{}),
+          create<DiscardStatement>(),
+          create<IfStatement>(nullptr, create<BlockStatement>(StatementList{}),
                               ElseStatementList{}),
       });
 
-  auto* continuing = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* continuing =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
 
-  LoopStatement l(Source{}, body, continuing);
-  EXPECT_FALSE(l.IsValid());
+  auto* l = create<LoopStatement>(body, continuing);
+  EXPECT_FALSE(l->IsValid());
 }
 
 TEST_F(LoopStatementTest, IsValid_NullContinuingStatement) {
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
 
-  auto* continuing =
-      create<BlockStatement>(Source{}, StatementList{
-                                           create<DiscardStatement>(Source{}),
-                                           nullptr,
-                                       });
+  auto* continuing = create<BlockStatement>(StatementList{
+      create<DiscardStatement>(),
+      nullptr,
+  });
 
-  LoopStatement l(Source{}, body, continuing);
-  EXPECT_FALSE(l.IsValid());
+  auto* l = create<LoopStatement>(body, continuing);
+  EXPECT_FALSE(l->IsValid());
 }
 
 TEST_F(LoopStatementTest, IsValid_InvalidContinuingStatement) {
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
 
   auto* continuing = create<BlockStatement>(
-      Source{},
+
       StatementList{
-          create<DiscardStatement>(Source{}),
-          create<IfStatement>(Source{}, nullptr,
-                              create<BlockStatement>(Source{}, StatementList{}),
+          create<DiscardStatement>(),
+          create<IfStatement>(nullptr, create<BlockStatement>(StatementList{}),
                               ElseStatementList{}),
       });
 
-  LoopStatement l(Source{}, body, continuing);
-  EXPECT_FALSE(l.IsValid());
+  auto* l = create<LoopStatement>(body, continuing);
+  EXPECT_FALSE(l->IsValid());
 }
 
 TEST_F(LoopStatementTest, ToStr) {
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
 
-  LoopStatement l(Source{}, body, {});
+  auto* l = create<LoopStatement>(body, nullptr);
   std::ostringstream out;
-  l.to_str(out, 2);
+  l->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(  Loop{
     Discard{}
   }
@@ -182,15 +179,15 @@
 }
 
 TEST_F(LoopStatementTest, ToStr_WithContinuing) {
-  auto* body = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* body =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
 
-  auto* continuing = create<BlockStatement>(
-      Source{}, StatementList{create<DiscardStatement>(Source{})});
+  auto* continuing =
+      create<BlockStatement>(StatementList{create<DiscardStatement>()});
 
-  LoopStatement l(Source{}, body, continuing);
+  auto* l = create<LoopStatement>(body, continuing);
   std::ostringstream out;
-  l.to_str(out, 2);
+  l->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(  Loop{
     Discard{}
     continuing {
diff --git a/src/ast/member_accessor_expression_test.cc b/src/ast/member_accessor_expression_test.cc
index 95a4f91..fb1d3a3 100644
--- a/src/ast/member_accessor_expression_test.cc
+++ b/src/ast/member_accessor_expression_test.cc
@@ -26,93 +26,85 @@
 using MemberAccessorExpressionTest = TestHelper;
 
 TEST_F(MemberAccessorExpressionTest, Creation) {
-  auto* str = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("structure"), "structure");
-  auto* mem = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("member"), "member");
+  auto* str = create<IdentifierExpression>(mod->RegisterSymbol("structure"),
+                                           "structure");
+  auto* mem = Expr("member");
 
-  MemberAccessorExpression stmt(Source{}, str, mem);
-  EXPECT_EQ(stmt.structure(), str);
-  EXPECT_EQ(stmt.member(), mem);
+  auto* stmt = create<MemberAccessorExpression>(str, mem);
+  EXPECT_EQ(stmt->structure(), str);
+  EXPECT_EQ(stmt->member(), mem);
 }
 
 TEST_F(MemberAccessorExpressionTest, Creation_WithSource) {
-  auto* str = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("structure"), "structure");
-  auto* mem = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("member"), "member");
+  auto* str = create<IdentifierExpression>(mod->RegisterSymbol("structure"),
+                                           "structure");
+  auto* mem = Expr("member");
 
-  MemberAccessorExpression stmt(Source{Source::Location{20, 2}}, str, mem);
-  auto src = stmt.source();
+  auto* stmt = create<MemberAccessorExpression>(Source{Source::Location{20, 2}},
+                                                str, mem);
+  auto src = stmt->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(MemberAccessorExpressionTest, IsMemberAccessor) {
-  auto* str = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("structure"), "structure");
-  auto* mem = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("member"), "member");
+  auto* str = create<IdentifierExpression>(mod->RegisterSymbol("structure"),
+                                           "structure");
+  auto* mem = Expr("member");
 
-  MemberAccessorExpression stmt(Source{}, str, mem);
-  EXPECT_TRUE(stmt.Is<MemberAccessorExpression>());
+  auto* stmt = create<MemberAccessorExpression>(str, mem);
+  EXPECT_TRUE(stmt->Is<MemberAccessorExpression>());
 }
 
 TEST_F(MemberAccessorExpressionTest, IsValid) {
-  auto* str = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("structure"), "structure");
-  auto* mem = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("member"), "member");
+  auto* str = create<IdentifierExpression>(mod->RegisterSymbol("structure"),
+                                           "structure");
+  auto* mem = Expr("member");
 
-  MemberAccessorExpression stmt(Source{}, str, mem);
-  EXPECT_TRUE(stmt.IsValid());
+  auto* stmt = create<MemberAccessorExpression>(str, mem);
+  EXPECT_TRUE(stmt->IsValid());
 }
 
 TEST_F(MemberAccessorExpressionTest, IsValid_NullStruct) {
-  auto* mem = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("member"), "member");
+  auto* mem = Expr("member");
 
-  MemberAccessorExpression stmt(Source{}, nullptr, mem);
-  EXPECT_FALSE(stmt.IsValid());
+  auto* stmt = create<MemberAccessorExpression>(nullptr, mem);
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(MemberAccessorExpressionTest, IsValid_InvalidStruct) {
-  auto* str =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol(""), "");
-  auto* mem = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("member"), "member");
+  auto* str = Expr("");
+  auto* mem = Expr("member");
 
-  MemberAccessorExpression stmt(Source{}, str, mem);
-  EXPECT_FALSE(stmt.IsValid());
+  auto* stmt = create<MemberAccessorExpression>(str, mem);
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(MemberAccessorExpressionTest, IsValid_NullMember) {
-  auto* str = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("structure"), "structure");
+  auto* str = create<IdentifierExpression>(mod->RegisterSymbol("structure"),
+                                           "structure");
 
-  MemberAccessorExpression stmt(Source{}, str, nullptr);
-  EXPECT_FALSE(stmt.IsValid());
+  auto* stmt = create<MemberAccessorExpression>(str, nullptr);
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(MemberAccessorExpressionTest, IsValid_InvalidMember) {
-  auto* str = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("structure"), "structure");
-  auto* mem =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol(""), "");
+  auto* str = create<IdentifierExpression>(mod->RegisterSymbol("structure"),
+                                           "structure");
+  auto* mem = Expr("");
 
-  MemberAccessorExpression stmt(Source{}, str, mem);
-  EXPECT_FALSE(stmt.IsValid());
+  auto* stmt = create<MemberAccessorExpression>(str, mem);
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(MemberAccessorExpressionTest, ToStr) {
-  auto* str = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("structure"), "structure");
-  auto* mem = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("member"), "member");
+  auto* str = create<IdentifierExpression>(mod->RegisterSymbol("structure"),
+                                           "structure");
+  auto* mem = Expr("member");
 
-  MemberAccessorExpression stmt(Source{}, str, mem);
+  auto* stmt = create<MemberAccessorExpression>(str, mem);
   std::ostringstream out;
-  stmt.to_str(out, 2);
+  stmt->to_str(out, 2);
   EXPECT_EQ(demangle(out.str()), R"(  MemberAccessor[not set]{
     Identifier[not set]{structure}
     Identifier[not set]{member}
diff --git a/src/ast/module_test.cc b/src/ast/module_test.cc
index 03be7eb..e826382 100644
--- a/src/ast/module_test.cc
+++ b/src/ast/module_test.cc
@@ -45,14 +45,12 @@
 }
 
 TEST_F(ModuleTest, LookupFunction) {
-  type::F32 f32;
   Module m;
 
   auto func_sym = m.RegisterSymbol("main");
-  auto* func =
-      create<Function>(Source{}, func_sym, "main", VariableList{}, &f32,
-                       create<BlockStatement>(Source{}, StatementList{}),
-                       ast::FunctionDecorationList{});
+  auto* func = create<Function>(func_sym, "main", VariableList{}, ty.f32,
+                                create<BlockStatement>(StatementList{}),
+                                ast::FunctionDecorationList{});
   m.AddFunction(func);
   EXPECT_EQ(func, m.FindFunctionBySymbol(func_sym));
 }
@@ -68,9 +66,8 @@
 }
 
 TEST_F(ModuleTest, IsValid_GlobalVariable) {
-  type::F32 f32;
-  auto* var = create<Variable>(Source{}, "var", StorageClass::kInput, &f32,
-                               false, nullptr, ast::VariableDecorationList{});
+  auto* var = create<Variable>("var", StorageClass::kInput, ty.f32, false,
+                               nullptr, ast::VariableDecorationList{});
 
   Module m;
   m.AddGlobalVariable(var);
@@ -84,8 +81,8 @@
 }
 
 TEST_F(ModuleTest, IsValid_Invalid_GlobalVariable) {
-  auto* var = create<Variable>(Source{}, "var", StorageClass::kInput, nullptr,
-                               false, nullptr, ast::VariableDecorationList{});
+  auto* var = create<Variable>("var", StorageClass::kInput, nullptr, false,
+                               nullptr, ast::VariableDecorationList{});
 
   Module m;
   m.AddGlobalVariable(var);
@@ -93,8 +90,7 @@
 }
 
 TEST_F(ModuleTest, IsValid_Alias) {
-  type::F32 f32;
-  type::Alias alias(mod.RegisterSymbol("alias"), "alias", &f32);
+  type::Alias alias(mod->RegisterSymbol("alias"), "alias", ty.f32);
 
   Module m;
   m.AddConstructedType(&alias);
@@ -108,9 +104,8 @@
 }
 
 TEST_F(ModuleTest, IsValid_Struct) {
-  type::F32 f32;
-  type::Struct st(mod.RegisterSymbol("name"), "name", {});
-  type::Alias alias(mod.RegisterSymbol("name"), "name", &st);
+  type::Struct st(mod->RegisterSymbol("name"), "name", {});
+  type::Alias alias(mod->RegisterSymbol("name"), "name", &st);
 
   Module m;
   m.AddConstructedType(&alias);
@@ -118,9 +113,8 @@
 }
 
 TEST_F(ModuleTest, IsValid_Struct_EmptyName) {
-  type::F32 f32;
-  type::Struct st(mod.RegisterSymbol(""), "", {});
-  type::Alias alias(mod.RegisterSymbol("name"), "name", &st);
+  type::Struct st(mod->RegisterSymbol(""), "", {});
+  type::Alias alias(mod->RegisterSymbol("name"), "name", &st);
 
   Module m;
   m.AddConstructedType(&alias);
@@ -128,14 +122,11 @@
 }
 
 TEST_F(ModuleTest, IsValid_Function) {
-  type::F32 f32;
-
   Module m;
 
   auto* func = create<Function>(
-      Source{}, m.RegisterSymbol("main"), "main", VariableList(), &f32,
-      create<BlockStatement>(Source{}, StatementList{}),
-      ast::FunctionDecorationList{});
+      m.RegisterSymbol("main"), "main", VariableList(), ty.f32,
+      create<BlockStatement>(StatementList{}), ast::FunctionDecorationList{});
 
   m.AddFunction(func);
   EXPECT_TRUE(m.IsValid());
@@ -152,9 +143,8 @@
 
   Module m;
 
-  auto* func =
-      create<Function>(Source{}, m.RegisterSymbol("main"), "main", p, nullptr,
-                       nullptr, ast::FunctionDecorationList{});
+  auto* func = create<Function>(m.RegisterSymbol("main"), "main", p, nullptr,
+                                nullptr, ast::FunctionDecorationList{});
 
   m.AddFunction(func);
   EXPECT_FALSE(m.IsValid());
diff --git a/src/ast/null_literal_test.cc b/src/ast/null_literal_test.cc
index 1d2afa0..025e02c 100644
--- a/src/ast/null_literal_test.cc
+++ b/src/ast/null_literal_test.cc
@@ -28,9 +28,7 @@
 using NullLiteralTest = TestHelper;
 
 TEST_F(NullLiteralTest, Is) {
-  type::I32 i32;
-  NullLiteral i{Source{}, &i32};
-  Literal* l = &i;
+  ast::Literal* l = create<NullLiteral>(ty.i32);
   EXPECT_FALSE(l->Is<BoolLiteral>());
   EXPECT_FALSE(l->Is<SintLiteral>());
   EXPECT_FALSE(l->Is<FloatLiteral>());
@@ -40,16 +38,14 @@
 }
 
 TEST_F(NullLiteralTest, ToStr) {
-  type::I32 i32;
-  NullLiteral i{Source{}, &i32};
+  auto* i = create<NullLiteral>(ty.i32);
 
-  EXPECT_EQ(i.to_str(), "null __i32");
+  EXPECT_EQ(i->to_str(), "null __i32");
 }
 
 TEST_F(NullLiteralTest, Name_I32) {
-  type::I32 i32;
-  NullLiteral i{Source{}, &i32};
-  EXPECT_EQ("__null__i32", i.name());
+  auto* i = create<NullLiteral>(ty.i32);
+  EXPECT_EQ("__null__i32", i->name());
 }
 
 }  // namespace
diff --git a/src/ast/return_statement_test.cc b/src/ast/return_statement_test.cc
index 221082d..68506c0 100644
--- a/src/ast/return_statement_test.cc
+++ b/src/ast/return_statement_test.cc
@@ -26,62 +26,57 @@
 using ReturnStatementTest = TestHelper;
 
 TEST_F(ReturnStatementTest, Creation) {
-  auto* expr = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("expr"), "expr");
+  auto* expr = Expr("expr");
 
-  ReturnStatement r(Source{}, expr);
-  EXPECT_EQ(r.value(), expr);
+  auto* r = create<ReturnStatement>(expr);
+  EXPECT_EQ(r->value(), expr);
 }
 
 TEST_F(ReturnStatementTest, Creation_WithSource) {
-  ReturnStatement r(Source{Source::Location{20, 2}});
-  auto src = r.source();
+  auto* r = create<ReturnStatement>(Source{Source::Location{20, 2}});
+  auto src = r->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(ReturnStatementTest, IsReturn) {
-  ReturnStatement r(Source{});
-  EXPECT_TRUE(r.Is<ReturnStatement>());
+  auto* r = create<ReturnStatement>();
+  EXPECT_TRUE(r->Is<ReturnStatement>());
 }
 
 TEST_F(ReturnStatementTest, HasValue_WithoutValue) {
-  ReturnStatement r(Source{});
-  EXPECT_FALSE(r.has_value());
+  auto* r = create<ReturnStatement>();
+  EXPECT_FALSE(r->has_value());
 }
 
 TEST_F(ReturnStatementTest, HasValue_WithValue) {
-  auto* expr = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("expr"), "expr");
-  ReturnStatement r(Source{}, expr);
-  EXPECT_TRUE(r.has_value());
+  auto* expr = Expr("expr");
+  auto* r = create<ReturnStatement>(expr);
+  EXPECT_TRUE(r->has_value());
 }
 
 TEST_F(ReturnStatementTest, IsValid_WithoutValue) {
-  ReturnStatement r(Source{});
-  EXPECT_TRUE(r.IsValid());
+  auto* r = create<ReturnStatement>();
+  EXPECT_TRUE(r->IsValid());
 }
 
 TEST_F(ReturnStatementTest, IsValid_WithValue) {
-  auto* expr = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("expr"), "expr");
-  ReturnStatement r(Source{}, expr);
-  EXPECT_TRUE(r.IsValid());
+  auto* expr = Expr("expr");
+  auto* r = create<ReturnStatement>(expr);
+  EXPECT_TRUE(r->IsValid());
 }
 
 TEST_F(ReturnStatementTest, IsValid_InvalidValue) {
-  auto* expr =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol(""), "");
-  ReturnStatement r(Source{}, expr);
-  EXPECT_FALSE(r.IsValid());
+  auto* expr = Expr("");
+  auto* r = create<ReturnStatement>(expr);
+  EXPECT_FALSE(r->IsValid());
 }
 
 TEST_F(ReturnStatementTest, ToStr_WithValue) {
-  auto* expr = create<IdentifierExpression>(Source{},
-                                            mod.RegisterSymbol("expr"), "expr");
-  ReturnStatement r(Source{}, expr);
+  auto* expr = Expr("expr");
+  auto* r = create<ReturnStatement>(expr);
   std::ostringstream out;
-  r.to_str(out, 2);
+  r->to_str(out, 2);
   EXPECT_EQ(demangle(out.str()), R"(  Return{
     {
       Identifier[not set]{expr}
@@ -91,9 +86,9 @@
 }
 
 TEST_F(ReturnStatementTest, ToStr_WithoutValue) {
-  ReturnStatement r(Source{});
+  auto* r = create<ReturnStatement>();
   std::ostringstream out;
-  r.to_str(out, 2);
+  r->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(  Return{}
 )");
 }
diff --git a/src/ast/scalar_constructor_expression_test.cc b/src/ast/scalar_constructor_expression_test.cc
index 4f648c3..14fbd96 100644
--- a/src/ast/scalar_constructor_expression_test.cc
+++ b/src/ast/scalar_constructor_expression_test.cc
@@ -26,38 +26,39 @@
 
 TEST_F(ScalarConstructorExpressionTest, Creation) {
   type::Bool bool_type;
-  auto* b = create<BoolLiteral>(Source{}, &bool_type, true);
-  ScalarConstructorExpression c(Source{}, b);
-  EXPECT_EQ(c.literal(), b);
+  auto* b = create<BoolLiteral>(&bool_type, true);
+  auto* c = create<ScalarConstructorExpression>(b);
+  EXPECT_EQ(c->literal(), b);
 }
 
 TEST_F(ScalarConstructorExpressionTest, Creation_WithSource) {
   type::Bool bool_type;
-  auto* b = create<BoolLiteral>(Source{}, &bool_type, true);
-  ScalarConstructorExpression c(Source{Source::Location{20, 2}}, b);
-  auto src = c.source();
+  auto* b = create<BoolLiteral>(&bool_type, true);
+  auto* c =
+      create<ScalarConstructorExpression>(Source{Source::Location{20, 2}}, b);
+  auto src = c->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(ScalarConstructorExpressionTest, IsValid) {
   type::Bool bool_type;
-  auto* b = create<BoolLiteral>(Source{}, &bool_type, true);
-  ScalarConstructorExpression c(Source{}, b);
-  EXPECT_TRUE(c.IsValid());
+  auto* b = create<BoolLiteral>(&bool_type, true);
+  auto* c = create<ScalarConstructorExpression>(b);
+  EXPECT_TRUE(c->IsValid());
 }
 
 TEST_F(ScalarConstructorExpressionTest, IsValid_MissingLiteral) {
-  ScalarConstructorExpression c(Source{}, nullptr);
-  EXPECT_FALSE(c.IsValid());
+  auto* c = create<ScalarConstructorExpression>(nullptr);
+  EXPECT_FALSE(c->IsValid());
 }
 
 TEST_F(ScalarConstructorExpressionTest, ToStr) {
   type::Bool bool_type;
-  auto* b = create<BoolLiteral>(Source{}, &bool_type, true);
-  ScalarConstructorExpression c(Source{}, b);
+  auto* b = create<BoolLiteral>(&bool_type, true);
+  auto* c = create<ScalarConstructorExpression>(b);
   std::ostringstream out;
-  c.to_str(out, 2);
+  c->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(  ScalarConstructor[not set]{true}
 )");
 }
diff --git a/src/ast/set_decoration_test.cc b/src/ast/set_decoration_test.cc
index c0d6a15..b5ae138 100644
--- a/src/ast/set_decoration_test.cc
+++ b/src/ast/set_decoration_test.cc
@@ -24,13 +24,12 @@
 using SetDecorationTest = TestHelper;
 
 TEST_F(SetDecorationTest, Creation) {
-  SetDecoration d{Source{}, 2};
-  EXPECT_EQ(2u, d.value());
+  auto* d = create<SetDecoration>(2);
+  EXPECT_EQ(2u, d->value());
 }
 
 TEST_F(SetDecorationTest, Is) {
-  SetDecoration sd{Source{}, 2};
-  Decoration* d = &sd;
+  Decoration* d = create<SetDecoration>(2);
   EXPECT_FALSE(d->Is<BindingDecoration>());
   EXPECT_FALSE(d->Is<BuiltinDecoration>());
   EXPECT_FALSE(d->Is<ConstantIdDecoration>());
@@ -39,9 +38,9 @@
 }
 
 TEST_F(SetDecorationTest, ToStr) {
-  SetDecoration d{Source{}, 2};
+  auto* d = create<SetDecoration>(2);
   std::ostringstream out;
-  d.to_str(out, 0);
+  d->to_str(out, 0);
   EXPECT_EQ(out.str(), R"(SetDecoration{2}
 )");
 }
diff --git a/src/ast/sint_literal_test.cc b/src/ast/sint_literal_test.cc
index f4fcc08..e4a32d2 100644
--- a/src/ast/sint_literal_test.cc
+++ b/src/ast/sint_literal_test.cc
@@ -29,16 +29,13 @@
 using SintLiteralTest = TestHelper;
 
 TEST_F(SintLiteralTest, Value) {
-  type::I32 i32;
-  SintLiteral i{Source{}, &i32, 47};
-  ASSERT_TRUE(i.Is<SintLiteral>());
-  EXPECT_EQ(i.value(), 47);
+  auto* i = create<SintLiteral>(ty.i32, 47);
+  ASSERT_TRUE(i->Is<SintLiteral>());
+  EXPECT_EQ(i->value(), 47);
 }
 
 TEST_F(SintLiteralTest, Is) {
-  type::I32 i32;
-  SintLiteral i{Source{}, &i32, 42};
-  Literal* l = &i;
+  ast::Literal* l = create<SintLiteral>(ty.i32, 42);
   EXPECT_FALSE(l->Is<BoolLiteral>());
   EXPECT_TRUE(l->Is<SintLiteral>());
   EXPECT_FALSE(l->Is<FloatLiteral>());
@@ -47,22 +44,20 @@
 }
 
 TEST_F(SintLiteralTest, ToStr) {
-  type::I32 i32;
-  SintLiteral i{Source{}, &i32, -42};
+  auto* i = create<SintLiteral>(ty.i32, -42);
 
-  EXPECT_EQ(i.to_str(), "-42");
+  EXPECT_EQ(i->to_str(), "-42");
 }
 
 TEST_F(SintLiteralTest, Name_I32) {
-  type::I32 i32;
-  SintLiteral i{Source{}, &i32, 2};
-  EXPECT_EQ("__sint__i32_2", i.name());
+  auto* i = create<SintLiteral>(ty.i32, 2);
+  EXPECT_EQ("__sint__i32_2", i->name());
 }
 
 TEST_F(SintLiteralTest, Name_U32) {
   type::U32 u32;
-  SintLiteral i{Source{}, &u32, 2};
-  EXPECT_EQ("__sint__u32_2", i.name());
+  auto* i = create<SintLiteral>(&u32, 2);
+  EXPECT_EQ("__sint__u32_2", i->name());
 }
 
 }  // namespace
diff --git a/src/ast/stage_decoration_test.cc b/src/ast/stage_decoration_test.cc
index 966d7e0..82a5ccd 100644
--- a/src/ast/stage_decoration_test.cc
+++ b/src/ast/stage_decoration_test.cc
@@ -26,21 +26,20 @@
 using StageDecorationTest = TestHelper;
 
 TEST_F(StageDecorationTest, Creation_1param) {
-  StageDecoration d{Source{}, PipelineStage::kFragment};
-  EXPECT_EQ(d.value(), PipelineStage::kFragment);
+  auto* d = create<StageDecoration>(PipelineStage::kFragment);
+  EXPECT_EQ(d->value(), PipelineStage::kFragment);
 }
 
 TEST_F(StageDecorationTest, Is) {
-  StageDecoration sd{Source{}, PipelineStage::kFragment};
-  Decoration* d = &sd;
+  Decoration* d = create<StageDecoration>(PipelineStage::kFragment);
   EXPECT_FALSE(d->Is<WorkgroupDecoration>());
   EXPECT_TRUE(d->Is<StageDecoration>());
 }
 
 TEST_F(StageDecorationTest, ToStr) {
-  StageDecoration d{Source{}, PipelineStage::kFragment};
+  auto* d = create<StageDecoration>(PipelineStage::kFragment);
   std::ostringstream out;
-  d.to_str(out, 0);
+  d->to_str(out, 0);
   EXPECT_EQ(out.str(), R"(StageDecoration{fragment}
 )");
 }
diff --git a/src/ast/stride_decoration_test.cc b/src/ast/stride_decoration_test.cc
index 34a1079..7046767 100644
--- a/src/ast/stride_decoration_test.cc
+++ b/src/ast/stride_decoration_test.cc
@@ -23,22 +23,22 @@
 using StrideDecorationTest = TestHelper;
 
 TEST_F(StrideDecorationTest, Creation) {
-  StrideDecoration d{Source{}, 2};
-  EXPECT_EQ(2u, d.stride());
+  auto* d = create<StrideDecoration>(2);
+  EXPECT_EQ(2u, d->stride());
 }
 
 TEST_F(StrideDecorationTest, Is) {
-  StrideDecoration d{Source{}, 2};
-  EXPECT_TRUE(d.Is<StrideDecoration>());
+  auto* d = create<StrideDecoration>(2);
+  EXPECT_TRUE(d->Is<StrideDecoration>());
 }
 
 TEST_F(StrideDecorationTest, Source) {
-  StrideDecoration d{
-      Source{Source::Range{Source::Location{1, 2}, Source::Location{3, 4}}}, 2};
-  EXPECT_EQ(d.source().range.begin.line, 1u);
-  EXPECT_EQ(d.source().range.begin.column, 2u);
-  EXPECT_EQ(d.source().range.end.line, 3u);
-  EXPECT_EQ(d.source().range.end.column, 4u);
+  auto* d = create<StrideDecoration>(
+      Source{Source::Range{Source::Location{1, 2}, Source::Location{3, 4}}}, 2);
+  EXPECT_EQ(d->source().range.begin.line, 1u);
+  EXPECT_EQ(d->source().range.begin.column, 2u);
+  EXPECT_EQ(d->source().range.end.line, 3u);
+  EXPECT_EQ(d->source().range.end.column, 4u);
 }
 
 }  // namespace
diff --git a/src/ast/struct_member_offset_decoration_test.cc b/src/ast/struct_member_offset_decoration_test.cc
index 49a4796..196bebb 100644
--- a/src/ast/struct_member_offset_decoration_test.cc
+++ b/src/ast/struct_member_offset_decoration_test.cc
@@ -23,13 +23,13 @@
 using StructMemberOffsetDecorationTest = TestHelper;
 
 TEST_F(StructMemberOffsetDecorationTest, Creation) {
-  StructMemberOffsetDecoration d{Source{}, 2};
-  EXPECT_EQ(2u, d.offset());
+  auto* d = create<StructMemberOffsetDecoration>(2);
+  EXPECT_EQ(2u, d->offset());
 }
 
 TEST_F(StructMemberOffsetDecorationTest, Is) {
-  StructMemberOffsetDecoration d{Source{}, 2};
-  EXPECT_TRUE(d.Is<StructMemberOffsetDecoration>());
+  auto* d = create<StructMemberOffsetDecoration>(2);
+  EXPECT_TRUE(d->Is<StructMemberOffsetDecoration>());
 }
 
 }  // namespace
diff --git a/src/ast/struct_member_test.cc b/src/ast/struct_member_test.cc
index 1c9a6d7..9130b96 100644
--- a/src/ast/struct_member_test.cc
+++ b/src/ast/struct_member_test.cc
@@ -28,78 +28,71 @@
 using StructMemberTest = TestHelper;
 
 TEST_F(StructMemberTest, Creation) {
-  type::I32 i32;
   StructMemberDecorationList decorations;
-  decorations.emplace_back(create<StructMemberOffsetDecoration>(Source{}, 4));
+  decorations.emplace_back(create<StructMemberOffsetDecoration>(4));
 
-  StructMember st{Source{}, "a", &i32, decorations};
-  EXPECT_EQ(st.name(), "a");
-  EXPECT_EQ(st.type(), &i32);
-  EXPECT_EQ(st.decorations().size(), 1u);
-  EXPECT_TRUE(st.decorations()[0]->Is<StructMemberOffsetDecoration>());
-  EXPECT_EQ(st.source().range.begin.line, 0u);
-  EXPECT_EQ(st.source().range.begin.column, 0u);
-  EXPECT_EQ(st.source().range.end.line, 0u);
-  EXPECT_EQ(st.source().range.end.column, 0u);
+  auto* st = create<StructMember>("a", ty.i32, decorations);
+  EXPECT_EQ(st->name(), "a");
+  EXPECT_EQ(st->type(), ty.i32);
+  EXPECT_EQ(st->decorations().size(), 1u);
+  EXPECT_TRUE(st->decorations()[0]->Is<StructMemberOffsetDecoration>());
+  EXPECT_EQ(st->source().range.begin.line, 0u);
+  EXPECT_EQ(st->source().range.begin.column, 0u);
+  EXPECT_EQ(st->source().range.end.line, 0u);
+  EXPECT_EQ(st->source().range.end.column, 0u);
 }
 
 TEST_F(StructMemberTest, CreationWithSource) {
-  type::I32 i32;
-  Source s{Source::Range{Source::Location{27, 4}, Source::Location{27, 8}}};
-
-  StructMember st{s, "a", &i32, {}};
-  EXPECT_EQ(st.name(), "a");
-  EXPECT_EQ(st.type(), &i32);
-  EXPECT_EQ(st.decorations().size(), 0u);
-  EXPECT_EQ(st.source().range.begin.line, 27u);
-  EXPECT_EQ(st.source().range.begin.column, 4u);
-  EXPECT_EQ(st.source().range.end.line, 27u);
-  EXPECT_EQ(st.source().range.end.column, 8u);
+  auto* st = create<StructMember>(
+      Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 8}}},
+      "a", ty.i32, StructMemberDecorationList{});
+  EXPECT_EQ(st->name(), "a");
+  EXPECT_EQ(st->type(), ty.i32);
+  EXPECT_EQ(st->decorations().size(), 0u);
+  EXPECT_EQ(st->source().range.begin.line, 27u);
+  EXPECT_EQ(st->source().range.begin.column, 4u);
+  EXPECT_EQ(st->source().range.end.line, 27u);
+  EXPECT_EQ(st->source().range.end.column, 8u);
 }
 
 TEST_F(StructMemberTest, IsValid) {
-  type::I32 i32;
-  StructMember st{Source{}, "a", &i32, {}};
-  EXPECT_TRUE(st.IsValid());
+  auto* st = create<StructMember>("a", ty.i32, StructMemberDecorationList{});
+  EXPECT_TRUE(st->IsValid());
 }
 
 TEST_F(StructMemberTest, IsValid_EmptyName) {
-  type::I32 i32;
-  StructMember st{Source{}, "", &i32, {}};
-  EXPECT_FALSE(st.IsValid());
+  auto* st = create<StructMember>("", ty.i32, StructMemberDecorationList{});
+  EXPECT_FALSE(st->IsValid());
 }
 
 TEST_F(StructMemberTest, IsValid_NullType) {
-  StructMember st{Source{}, "a", nullptr, {}};
-  EXPECT_FALSE(st.IsValid());
+  auto* st = create<StructMember>("a", nullptr, StructMemberDecorationList{});
+  EXPECT_FALSE(st->IsValid());
 }
 
 TEST_F(StructMemberTest, IsValid_Null_Decoration) {
-  type::I32 i32;
   StructMemberDecorationList decorations;
-  decorations.emplace_back(create<StructMemberOffsetDecoration>(Source{}, 4));
+  decorations.emplace_back(create<StructMemberOffsetDecoration>(4));
   decorations.push_back(nullptr);
 
-  StructMember st{Source{}, "a", &i32, decorations};
-  EXPECT_FALSE(st.IsValid());
+  auto* st = create<StructMember>("a", ty.i32, decorations);
+  EXPECT_FALSE(st->IsValid());
 }
 
 TEST_F(StructMemberTest, ToStr) {
-  type::I32 i32;
   StructMemberDecorationList decorations;
-  decorations.emplace_back(create<StructMemberOffsetDecoration>(Source{}, 4));
+  decorations.emplace_back(create<StructMemberOffsetDecoration>(4));
 
-  StructMember st{Source{}, "a", &i32, decorations};
+  auto* st = create<StructMember>("a", ty.i32, decorations);
   std::ostringstream out;
-  st.to_str(out, 2);
+  st->to_str(out, 2);
   EXPECT_EQ(out.str(), "  StructMember{[[ offset 4 ]] a: __i32}\n");
 }
 
 TEST_F(StructMemberTest, ToStrNoDecorations) {
-  type::I32 i32;
-  StructMember st{Source{}, "a", &i32, {}};
+  auto* st = create<StructMember>("a", ty.i32, StructMemberDecorationList{});
   std::ostringstream out;
-  st.to_str(out, 2);
+  st->to_str(out, 2);
   EXPECT_EQ(out.str(), "  StructMember{a: __i32}\n");
 }
 
diff --git a/src/ast/struct_test.cc b/src/ast/struct_test.cc
index 5f0f1f0..9ad9c91 100644
--- a/src/ast/struct_test.cc
+++ b/src/ast/struct_test.cc
@@ -30,104 +30,93 @@
 using StructTest = TestHelper;
 
 TEST_F(StructTest, Creation) {
-  type::I32 i32;
   StructMemberList members;
   members.push_back(
-      create<StructMember>(Source{}, "a", &i32, StructMemberDecorationList()));
+      create<StructMember>("a", ty.i32, StructMemberDecorationList{}));
 
-  Struct s{Source{}, members, ast::StructDecorationList{}};
-  EXPECT_EQ(s.members().size(), 1u);
-  EXPECT_TRUE(s.decorations().empty());
-  EXPECT_EQ(s.source().range.begin.line, 0u);
-  EXPECT_EQ(s.source().range.begin.column, 0u);
-  EXPECT_EQ(s.source().range.end.line, 0u);
-  EXPECT_EQ(s.source().range.end.column, 0u);
-}
+  auto* s = create<Struct>(members, ast::StructDecorationList{});
+  EXPECT_EQ(s->members().size(), 1u);
+  EXPECT_TRUE(s->decorations().empty());
+  EXPECT_EQ(s->source().range.begin.line, 0u);
+  EXPECT_EQ(s->source().range.begin.column, 0u);
+  EXPECT_EQ(s->source().range.end.line, 0u);
+  EXPECT_EQ(s->source().range.end.column, 0u);
+}  // namespace
 
 TEST_F(StructTest, Creation_WithDecorations) {
-  type::I32 i32;
-
   StructMemberList members;
   members.push_back(
-      create<StructMember>(Source{}, "a", &i32, StructMemberDecorationList()));
+      create<StructMember>("a", ty.i32, StructMemberDecorationList{}));
 
   StructDecorationList decos;
-  decos.push_back(create<StructBlockDecoration>(Source{}));
+  decos.push_back(create<StructBlockDecoration>());
 
-  Struct s{Source{}, members, decos};
-  EXPECT_EQ(s.members().size(), 1u);
-  ASSERT_EQ(s.decorations().size(), 1u);
-  EXPECT_TRUE(s.decorations()[0]->Is<StructBlockDecoration>());
-  EXPECT_EQ(s.source().range.begin.line, 0u);
-  EXPECT_EQ(s.source().range.begin.column, 0u);
-  EXPECT_EQ(s.source().range.end.line, 0u);
-  EXPECT_EQ(s.source().range.end.column, 0u);
+  auto* s = create<Struct>(members, decos);
+  EXPECT_EQ(s->members().size(), 1u);
+  ASSERT_EQ(s->decorations().size(), 1u);
+  EXPECT_TRUE(s->decorations()[0]->Is<StructBlockDecoration>());
+  EXPECT_EQ(s->source().range.begin.line, 0u);
+  EXPECT_EQ(s->source().range.begin.column, 0u);
+  EXPECT_EQ(s->source().range.end.line, 0u);
+  EXPECT_EQ(s->source().range.end.column, 0u);
 }
 
 TEST_F(StructTest, CreationWithSourceAndDecorations) {
-  type::I32 i32;
-
   StructMemberList members;
   members.emplace_back(
-      create<StructMember>(Source{}, "a", &i32, StructMemberDecorationList()));
+      create<StructMember>("a", ty.i32, StructMemberDecorationList{}));
 
   StructDecorationList decos;
-  decos.push_back(create<StructBlockDecoration>(Source{}));
+  decos.push_back(create<StructBlockDecoration>());
 
-  Struct s{
+  auto* s = create<Struct>(
       Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 8}}},
-      members, decos};
-  EXPECT_EQ(s.members().size(), 1u);
-  ASSERT_EQ(s.decorations().size(), 1u);
-  EXPECT_TRUE(s.decorations()[0]->Is<StructBlockDecoration>());
-  EXPECT_EQ(s.source().range.begin.line, 27u);
-  EXPECT_EQ(s.source().range.begin.column, 4u);
-  EXPECT_EQ(s.source().range.end.line, 27u);
-  EXPECT_EQ(s.source().range.end.column, 8u);
+      members, decos);
+  EXPECT_EQ(s->members().size(), 1u);
+  ASSERT_EQ(s->decorations().size(), 1u);
+  EXPECT_TRUE(s->decorations()[0]->Is<StructBlockDecoration>());
+  EXPECT_EQ(s->source().range.begin.line, 27u);
+  EXPECT_EQ(s->source().range.begin.column, 4u);
+  EXPECT_EQ(s->source().range.end.line, 27u);
+  EXPECT_EQ(s->source().range.end.column, 8u);
 }
 
 TEST_F(StructTest, IsValid) {
-  Struct s(Source{}, StructMemberList{}, StructDecorationList{});
-  EXPECT_TRUE(s.IsValid());
+  auto* s = create<Struct>(StructMemberList{}, StructDecorationList{});
+  EXPECT_TRUE(s->IsValid());
 }
 
 TEST_F(StructTest, IsValid_Null_StructMember) {
-  type::I32 i32;
-
   StructMemberList members;
   members.push_back(
-      create<StructMember>(Source{}, "a", &i32, StructMemberDecorationList()));
+      create<StructMember>("a", ty.i32, StructMemberDecorationList{}));
   members.push_back(nullptr);
 
-  Struct s{Source{}, members, ast::StructDecorationList{}};
-  EXPECT_FALSE(s.IsValid());
-}
+  auto* s = create<Struct>(members, ast::StructDecorationList{});
+  EXPECT_FALSE(s->IsValid());
+}  // namespace ast
 
 TEST_F(StructTest, IsValid_Invalid_StructMember) {
-  type::I32 i32;
-
   StructMemberList members;
   members.push_back(
-      create<StructMember>(Source{}, "", &i32, StructMemberDecorationList()));
+      create<StructMember>("", ty.i32, StructMemberDecorationList{}));
 
-  Struct s{Source{}, members, ast::StructDecorationList{}};
-  EXPECT_FALSE(s.IsValid());
-}
+  auto* s = create<Struct>(members, ast::StructDecorationList{});
+  EXPECT_FALSE(s->IsValid());
+}  // namespace tint
 
 TEST_F(StructTest, ToStr) {
-  type::I32 i32;
-
   StructMemberList members;
   members.emplace_back(
-      create<StructMember>(Source{}, "a", &i32, StructMemberDecorationList()));
+      create<StructMember>("a", ty.i32, StructMemberDecorationList{}));
 
   StructDecorationList decos;
-  decos.push_back(create<StructBlockDecoration>(Source{}));
+  decos.push_back(create<StructBlockDecoration>());
 
-  Struct s{Source{}, members, decos};
+  auto* s = create<Struct>(members, decos);
 
   std::ostringstream out;
-  s.to_str(out, 2);
+  s->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(Struct{
     [[block]]
     StructMember{a: __i32}
diff --git a/src/ast/switch_statement_test.cc b/src/ast/switch_statement_test.cc
index bb5ce31..1753658 100644
--- a/src/ast/switch_statement_test.cc
+++ b/src/ast/switch_statement_test.cc
@@ -29,136 +29,115 @@
 using SwitchStatementTest = TestHelper;
 
 TEST_F(SwitchStatementTest, Creation) {
-  type::I32 i32;
-
   CaseSelectorList lit;
-  lit.push_back(create<SintLiteral>(Source{}, &i32, 1));
+  lit.push_back(create<SintLiteral>(ty.i32, 1));
 
-  auto* ident = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("ident"), "ident");
+  auto* ident = Expr("ident");
   CaseStatementList body;
-  auto* case_stmt = create<CaseStatement>(
-      Source{}, lit, create<BlockStatement>(Source{}, StatementList{}));
+  auto* case_stmt =
+      create<CaseStatement>(lit, create<BlockStatement>(StatementList{}));
   body.push_back(case_stmt);
 
-  SwitchStatement stmt(Source{}, ident, body);
-  EXPECT_EQ(stmt.condition(), ident);
-  ASSERT_EQ(stmt.body().size(), 1u);
-  EXPECT_EQ(stmt.body()[0], case_stmt);
+  auto* stmt = create<SwitchStatement>(ident, body);
+  EXPECT_EQ(stmt->condition(), ident);
+  ASSERT_EQ(stmt->body().size(), 1u);
+  EXPECT_EQ(stmt->body()[0], case_stmt);
 }
 
 TEST_F(SwitchStatementTest, Creation_WithSource) {
-  auto* ident = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("ident"), "ident");
+  auto* ident = Expr("ident");
 
-  SwitchStatement stmt(Source{Source::Location{20, 2}}, ident,
-                       CaseStatementList());
-  auto src = stmt.source();
+  auto* stmt = create<SwitchStatement>(Source{Source::Location{20, 2}}, ident,
+                                       CaseStatementList());
+  auto src = stmt->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(SwitchStatementTest, IsSwitch) {
-  type::I32 i32;
-
   CaseSelectorList lit;
-  lit.push_back(create<SintLiteral>(Source{}, &i32, 2));
+  lit.push_back(create<SintLiteral>(ty.i32, 2));
 
-  auto* ident = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("ident"), "ident");
+  auto* ident = Expr("ident");
   CaseStatementList body;
-  body.push_back(create<CaseStatement>(
-      Source{}, lit, create<BlockStatement>(Source{}, StatementList{})));
+  body.push_back(
+      create<CaseStatement>(lit, create<BlockStatement>(StatementList{})));
 
-  SwitchStatement stmt(Source{}, ident, body);
-  EXPECT_TRUE(stmt.Is<SwitchStatement>());
+  auto* stmt = create<SwitchStatement>(ident, body);
+  EXPECT_TRUE(stmt->Is<SwitchStatement>());
 }
 
 TEST_F(SwitchStatementTest, IsValid) {
-  type::I32 i32;
-
   CaseSelectorList lit;
-  lit.push_back(create<SintLiteral>(Source{}, &i32, 2));
+  lit.push_back(create<SintLiteral>(ty.i32, 2));
 
-  auto* ident = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("ident"), "ident");
+  auto* ident = Expr("ident");
   CaseStatementList body;
-  body.push_back(create<CaseStatement>(
-      Source{}, lit, create<BlockStatement>(Source{}, StatementList{})));
+  body.push_back(
+      create<CaseStatement>(lit, create<BlockStatement>(StatementList{})));
 
-  SwitchStatement stmt(Source{}, ident, body);
-  EXPECT_TRUE(stmt.IsValid());
+  auto* stmt = create<SwitchStatement>(ident, body);
+  EXPECT_TRUE(stmt->IsValid());
 }
 
 TEST_F(SwitchStatementTest, IsValid_Null_Condition) {
-  type::I32 i32;
-
   CaseSelectorList lit;
-  lit.push_back(create<SintLiteral>(Source{}, &i32, 2));
+  lit.push_back(create<SintLiteral>(ty.i32, 2));
 
   CaseStatementList body;
-  body.push_back(create<CaseStatement>(
-      Source{}, lit, create<BlockStatement>(Source{}, StatementList{})));
+  body.push_back(
+      create<CaseStatement>(lit, create<BlockStatement>(StatementList{})));
 
-  SwitchStatement stmt(Source{}, nullptr, body);
-  EXPECT_FALSE(stmt.IsValid());
+  auto* stmt = create<SwitchStatement>(nullptr, body);
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(SwitchStatementTest, IsValid_Invalid_Condition) {
-  type::I32 i32;
-
   CaseSelectorList lit;
-  lit.push_back(create<SintLiteral>(Source{}, &i32, 2));
+  lit.push_back(create<SintLiteral>(ty.i32, 2));
 
-  auto* ident =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol(""), "");
+  auto* ident = Expr("");
   CaseStatementList body;
-  body.push_back(create<CaseStatement>(
-      Source{}, lit, create<BlockStatement>(Source{}, StatementList{})));
+  body.push_back(
+      create<CaseStatement>(lit, create<BlockStatement>(StatementList{})));
 
-  SwitchStatement stmt(Source{}, ident, body);
-  EXPECT_FALSE(stmt.IsValid());
+  auto* stmt = create<SwitchStatement>(ident, body);
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(SwitchStatementTest, IsValid_Null_BodyStatement) {
-  type::I32 i32;
-
   CaseSelectorList lit;
-  lit.push_back(create<SintLiteral>(Source{}, &i32, 2));
+  lit.push_back(create<SintLiteral>(ty.i32, 2));
 
-  auto* ident = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("ident"), "ident");
+  auto* ident = Expr("ident");
   CaseStatementList body;
-  body.push_back(create<CaseStatement>(
-      Source{}, lit, create<BlockStatement>(Source{}, StatementList{})));
+  body.push_back(
+      create<CaseStatement>(lit, create<BlockStatement>(StatementList{})));
   body.push_back(nullptr);
 
-  SwitchStatement stmt(Source{}, ident, body);
-  EXPECT_FALSE(stmt.IsValid());
+  auto* stmt = create<SwitchStatement>(ident, body);
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(SwitchStatementTest, IsValid_Invalid_BodyStatement) {
-  auto* ident = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("ident"), "ident");
+  auto* ident = Expr("ident");
 
-  auto* case_body = create<BlockStatement>(Source{}, StatementList{
-                                                         nullptr,
-                                                     });
+  auto* case_body = create<BlockStatement>(StatementList{
+      nullptr,
+  });
   CaseStatementList body;
-  body.push_back(
-      create<CaseStatement>(Source{}, CaseSelectorList{}, case_body));
+  body.push_back(create<CaseStatement>(CaseSelectorList{}, case_body));
 
-  SwitchStatement stmt(Source{}, ident, body);
-  EXPECT_FALSE(stmt.IsValid());
+  auto* stmt = create<SwitchStatement>(ident, body);
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(SwitchStatementTest, ToStr_Empty) {
-  auto* ident = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("ident"), "ident");
+  auto* ident = Expr("ident");
 
-  SwitchStatement stmt(Source{}, ident, {});
+  auto* stmt = create<SwitchStatement>(ident, CaseStatementList{});
   std::ostringstream out;
-  stmt.to_str(out, 2);
+  stmt->to_str(out, 2);
   EXPECT_EQ(demangle(out.str()), R"(  Switch{
     Identifier[not set]{ident}
     {
@@ -168,20 +147,17 @@
 }
 
 TEST_F(SwitchStatementTest, ToStr) {
-  type::I32 i32;
-
   CaseSelectorList lit;
-  lit.push_back(create<SintLiteral>(Source{}, &i32, 2));
+  lit.push_back(create<SintLiteral>(ty.i32, 2));
 
-  auto* ident = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("ident"), "ident");
+  auto* ident = Expr("ident");
   CaseStatementList body;
-  body.push_back(create<CaseStatement>(
-      Source{}, lit, create<BlockStatement>(Source{}, StatementList{})));
+  body.push_back(
+      create<CaseStatement>(lit, create<BlockStatement>(StatementList{})));
 
-  SwitchStatement stmt(Source{}, ident, body);
+  auto* stmt = create<SwitchStatement>(ident, body);
   std::ostringstream out;
-  stmt.to_str(out, 2);
+  stmt->to_str(out, 2);
   EXPECT_EQ(demangle(out.str()), R"(  Switch{
     Identifier[not set]{ident}
     {
diff --git a/src/ast/test_helper.h b/src/ast/test_helper.h
index 5bb3402..7cb44f8 100644
--- a/src/ast/test_helper.h
+++ b/src/ast/test_helper.h
@@ -20,6 +20,7 @@
 #include <utility>
 
 #include "gtest/gtest.h"
+#include "src/ast/builder.h"
 #include "src/ast/module.h"
 #include "src/demangler.h"
 
@@ -28,29 +29,15 @@
 
 /// Helper class for testing
 template <typename BASE>
-class TestHelperBase : public BASE {
+class TestHelperBase : public BASE, public BuilderWithModule {
  public:
-  TestHelperBase() {}
-  ~TestHelperBase() = default;
-
-  /// Creates a new `Node` owned by the Module. When the Module is
-  /// destructed, the `Node` will also be destructed.
-  /// @param args the arguments to pass to the type constructor
-  /// @returns the node pointer
-  template <typename T, typename... ARGS>
-  T* create(ARGS&&... args) {
-    return mod.create<T>(std::forward<ARGS>(args)...);
-  }
-
   /// Demangles the given string
   /// @param s the string to demangle
   /// @returns the demangled string
   std::string demangle(const std::string& s) {
-    return demanger.Demangle(mod, s);
+    return demanger.Demangle(*mod, s);
   }
 
-  /// The module
-  Module mod;
   /// A demangler
   Demangler demanger;
 };
diff --git a/src/ast/type/access_control_type_test.cc b/src/ast/type/access_control_type_test.cc
index ef803ac..37d93d9 100644
--- a/src/ast/type/access_control_type_test.cc
+++ b/src/ast/type/access_control_type_test.cc
@@ -106,16 +106,14 @@
 
 TEST_F(AccessControlTest, MinBufferBindingSizeArray) {
   U32 u32;
-  Array array(&u32, 4,
-              ArrayDecorationList{create<StrideDecoration>(Source{}, 4)});
+  Array array(&u32, 4, ArrayDecorationList{create<StrideDecoration>(4)});
   AccessControl at{ast::AccessControl::kReadOnly, &array};
   EXPECT_EQ(16u, at.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
 }
 
 TEST_F(AccessControlTest, MinBufferBindingSizeRuntimeArray) {
   U32 u32;
-  Array array(&u32, 0,
-              ArrayDecorationList{create<StrideDecoration>(Source{}, 4)});
+  Array array(&u32, 0, ArrayDecorationList{create<StrideDecoration>(4)});
   AccessControl at{ast::AccessControl::kReadOnly, &array};
   EXPECT_EQ(4u, at.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
 }
@@ -125,17 +123,17 @@
   StructMemberList members;
 
   StructMemberDecorationList deco;
-  deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 0));
-  members.push_back(create<StructMember>(Source{}, "foo", &u32, deco));
+  deco.push_back(create<StructMemberOffsetDecoration>(0));
+  members.push_back(create<StructMember>("foo", &u32, deco));
 
   deco = StructMemberDecorationList();
-  deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 4));
-  members.push_back(create<StructMember>(Source{}, "bar", &u32, deco));
+  deco.push_back(create<StructMemberOffsetDecoration>(4));
+  members.push_back(create<StructMember>("bar", &u32, deco));
 
   StructDecorationList decos;
 
-  auto* str = create<ast::Struct>(Source{}, members, decos);
-  Struct struct_type(mod.RegisterSymbol("struct_type"), "struct_type", str);
+  auto* str = create<ast::Struct>(members, decos);
+  Struct struct_type(mod->RegisterSymbol("struct_type"), "struct_type", str);
   AccessControl at{ast::AccessControl::kReadOnly, &struct_type};
   EXPECT_EQ(16u, at.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(8u, at.MinBufferBindingSize(MemoryLayout::kStorageBuffer));
@@ -149,16 +147,14 @@
 
 TEST_F(AccessControlTest, BaseAlignmentArray) {
   U32 u32;
-  Array array(&u32, 4,
-              ArrayDecorationList{create<StrideDecoration>(Source{}, 4)});
+  Array array(&u32, 4, ArrayDecorationList{create<StrideDecoration>(4)});
   AccessControl at{ast::AccessControl::kReadOnly, &array};
   EXPECT_EQ(16u, at.BaseAlignment(MemoryLayout::kUniformBuffer));
 }
 
 TEST_F(AccessControlTest, BaseAlignmentRuntimeArray) {
   U32 u32;
-  Array array(&u32, 0,
-              ArrayDecorationList{create<StrideDecoration>(Source{}, 4)});
+  Array array(&u32, 0, ArrayDecorationList{create<StrideDecoration>(4)});
   AccessControl at{ast::AccessControl::kReadOnly, &array};
   EXPECT_EQ(16u, at.BaseAlignment(MemoryLayout::kUniformBuffer));
 }
@@ -169,18 +165,18 @@
 
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 0));
-    members.push_back(create<StructMember>(Source{}, "foo", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(0));
+    members.push_back(create<StructMember>("foo", &u32, deco));
   }
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 4));
-    members.push_back(create<StructMember>(Source{}, "bar", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(4));
+    members.push_back(create<StructMember>("bar", &u32, deco));
   }
   StructDecorationList decos;
 
-  auto* str = create<ast::Struct>(Source{}, members, decos);
-  Struct struct_type(mod.RegisterSymbol("struct_type"), "struct_type", str);
+  auto* str = create<ast::Struct>(members, decos);
+  Struct struct_type(mod->RegisterSymbol("struct_type"), "struct_type", str);
   AccessControl at{ast::AccessControl::kReadOnly, &struct_type};
   EXPECT_EQ(16u, at.BaseAlignment(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(4u, at.BaseAlignment(MemoryLayout::kStorageBuffer));
diff --git a/src/ast/type/alias_type_test.cc b/src/ast/type/alias_type_test.cc
index dc34994..6cc025b 100644
--- a/src/ast/type/alias_type_test.cc
+++ b/src/ast/type/alias_type_test.cc
@@ -44,7 +44,7 @@
 
 TEST_F(AliasTest, Create) {
   U32 u32;
-  Alias a{mod.RegisterSymbol("a_type"), "a_type", &u32};
+  Alias a{mod->RegisterSymbol("a_type"), "a_type", &u32};
   EXPECT_EQ(a.symbol(), Symbol(1));
   // EXPECT_EQ(a.name(), "a_type");
   EXPECT_EQ(a.type(), &u32);
@@ -53,7 +53,7 @@
 TEST_F(AliasTest, Is) {
   I32 i32;
 
-  Alias at{mod.RegisterSymbol("a"), "a", &i32};
+  Alias at{mod->RegisterSymbol("a"), "a", &i32};
   Type* ty = &at;
   EXPECT_FALSE(ty->Is<AccessControl>());
   EXPECT_TRUE(ty->Is<Alias>());
@@ -72,13 +72,13 @@
 
 TEST_F(AliasTest, TypeName) {
   I32 i32;
-  Alias at{mod.RegisterSymbol("Particle"), "Particle", &i32};
+  Alias at{mod->RegisterSymbol("Particle"), "Particle", &i32};
   EXPECT_EQ(at.type_name(), "__alias_tint_symbol_1__i32");
 }
 
 TEST_F(AliasTest, UnwrapIfNeeded_Alias) {
   U32 u32;
-  Alias a{mod.RegisterSymbol("a_type"), "a_type", &u32};
+  Alias a{mod->RegisterSymbol("a_type"), "a_type", &u32};
   EXPECT_EQ(a.symbol(), Symbol(1));
   // EXPECT_EQ(a.name(), "a_type");
   EXPECT_EQ(a.type(), &u32);
@@ -95,8 +95,8 @@
 
 TEST_F(AliasTest, UnwrapIfNeeded_MultiLevel) {
   U32 u32;
-  Alias a{mod.RegisterSymbol("a_type"), "a_type", &u32};
-  Alias aa{mod.RegisterSymbol("aa_type"), "aa_type", &a};
+  Alias a{mod->RegisterSymbol("a_type"), "a_type", &u32};
+  Alias aa{mod->RegisterSymbol("aa_type"), "aa_type", &a};
   EXPECT_EQ(aa.symbol(), Symbol(2));
   // EXPECT_EQ(aa.name(), "aa_type");
   EXPECT_EQ(aa.type(), &a);
@@ -105,7 +105,7 @@
 
 TEST_F(AliasTest, UnwrapIfNeeded_MultiLevel_AliasAccessControl) {
   U32 u32;
-  Alias a{mod.RegisterSymbol("a_type"), "a_type", &u32};
+  Alias a{mod->RegisterSymbol("a_type"), "a_type", &u32};
   AccessControl aa{ast::AccessControl::kReadWrite, &a};
   EXPECT_EQ(aa.type(), &a);
   EXPECT_EQ(aa.UnwrapIfNeeded(), &u32);
@@ -113,11 +113,11 @@
 
 TEST_F(AliasTest, UnwrapAll_TwiceAliasPointerTwiceAlias) {
   U32 u32;
-  Alias a{mod.RegisterSymbol("a_type"), "a_type", &u32};
-  Alias aa{mod.RegisterSymbol("aa_type"), "aa_type", &a};
+  Alias a{mod->RegisterSymbol("a_type"), "a_type", &u32};
+  Alias aa{mod->RegisterSymbol("aa_type"), "aa_type", &a};
   Pointer paa{&aa, StorageClass::kUniform};
-  Alias apaa{mod.RegisterSymbol("paa_type"), "paa_type", &paa};
-  Alias aapaa{mod.RegisterSymbol("aapaa_type"), "aapaa_type", &apaa};
+  Alias apaa{mod->RegisterSymbol("paa_type"), "paa_type", &paa};
+  Alias aapaa{mod->RegisterSymbol("aapaa_type"), "aapaa_type", &apaa};
   EXPECT_EQ(aapaa.symbol(), Symbol(4));
   // EXPECT_EQ(aapaa.name(), "aapaa_type");
   EXPECT_EQ(aapaa.type(), &apaa);
@@ -127,23 +127,23 @@
 
 TEST_F(AliasTest, UnwrapAll_SecondConsecutivePointerBlocksUnrapping) {
   U32 u32;
-  Alias a{mod.RegisterSymbol("a_type"), "a_type", &u32};
-  Alias aa{mod.RegisterSymbol("aa_type"), "aa_type", &a};
+  Alias a{mod->RegisterSymbol("a_type"), "a_type", &u32};
+  Alias aa{mod->RegisterSymbol("aa_type"), "aa_type", &a};
   Pointer paa{&aa, StorageClass::kUniform};
   Pointer ppaa{&paa, StorageClass::kUniform};
-  Alias appaa{mod.RegisterSymbol("appaa_type"), "appaa_type", &ppaa};
+  Alias appaa{mod->RegisterSymbol("appaa_type"), "appaa_type", &ppaa};
   EXPECT_EQ(appaa.UnwrapAll(), &paa);
 }
 
 TEST_F(AliasTest, UnwrapAll_SecondNonConsecutivePointerBlocksUnrapping) {
   U32 u32;
-  Alias a{mod.RegisterSymbol("a_type"), "a_type", &u32};
-  Alias aa{mod.RegisterSymbol("aa_type"), "aa_type", &a};
+  Alias a{mod->RegisterSymbol("a_type"), "a_type", &u32};
+  Alias aa{mod->RegisterSymbol("aa_type"), "aa_type", &a};
   Pointer paa{&aa, StorageClass::kUniform};
-  Alias apaa{mod.RegisterSymbol("apaa_type"), "apaa_type", &paa};
-  Alias aapaa{mod.RegisterSymbol("aapaa_type"), "aapaa_type", &apaa};
+  Alias apaa{mod->RegisterSymbol("apaa_type"), "apaa_type", &paa};
+  Alias aapaa{mod->RegisterSymbol("aapaa_type"), "aapaa_type", &apaa};
   Pointer paapaa{&aapaa, StorageClass::kUniform};
-  Alias apaapaa{mod.RegisterSymbol("apaapaa_type"), "apaapaa_type", &paapaa};
+  Alias apaapaa{mod->RegisterSymbol("apaapaa_type"), "apaapaa_type", &paapaa};
   EXPECT_EQ(apaapaa.UnwrapAll(), &paa);
 }
 
@@ -167,7 +167,7 @@
 
 TEST_F(AliasTest, MinBufferBindingSizeU32) {
   U32 u32;
-  Alias alias{mod.RegisterSymbol("alias"), "alias", &u32};
+  Alias alias{mod->RegisterSymbol("alias"), "alias", &u32};
   EXPECT_EQ(4u, alias.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
 }
 
@@ -175,9 +175,9 @@
   U32 u32;
   Array array(&u32, 4,
               ArrayDecorationList{
-                  create<StrideDecoration>(Source{}, 4),
+                  create<StrideDecoration>(4),
               });
-  Alias alias{mod.RegisterSymbol("alias"), "alias", &array};
+  Alias alias{mod->RegisterSymbol("alias"), "alias", &array};
   EXPECT_EQ(16u, alias.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
 }
 
@@ -185,9 +185,9 @@
   U32 u32;
   Array array(&u32, 0,
               ArrayDecorationList{
-                  create<StrideDecoration>(Source{}, 4),
+                  create<StrideDecoration>(4),
               });
-  Alias alias{mod.RegisterSymbol("alias"), "alias", &array};
+  Alias alias{mod->RegisterSymbol("alias"), "alias", &array};
   EXPECT_EQ(4u, alias.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
 }
 
@@ -197,26 +197,26 @@
 
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 0));
-    members.push_back(create<StructMember>(Source{}, "foo", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(0));
+    members.push_back(create<StructMember>("foo", &u32, deco));
   }
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 4));
-    members.push_back(create<StructMember>(Source{}, "bar", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(4));
+    members.push_back(create<StructMember>("bar", &u32, deco));
   }
   StructDecorationList decos;
 
-  auto* str = create<ast::Struct>(Source{}, members, decos);
-  Struct struct_type(mod.RegisterSymbol("struct_type"), "struct_type", str);
-  Alias alias{mod.RegisterSymbol("alias"), "alias", &struct_type};
+  auto* str = create<ast::Struct>(members, decos);
+  Struct struct_type(mod->RegisterSymbol("struct_type"), "struct_type", str);
+  Alias alias{mod->RegisterSymbol("alias"), "alias", &struct_type};
   EXPECT_EQ(16u, alias.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(8u, alias.MinBufferBindingSize(MemoryLayout::kStorageBuffer));
 }
 
 TEST_F(AliasTest, BaseAlignmentU32) {
   U32 u32;
-  Alias alias{mod.RegisterSymbol("alias"), "alias", &u32};
+  Alias alias{mod->RegisterSymbol("alias"), "alias", &u32};
   EXPECT_EQ(4u, alias.BaseAlignment(MemoryLayout::kUniformBuffer));
 }
 
@@ -224,9 +224,9 @@
   U32 u32;
   Array array(&u32, 4,
               ArrayDecorationList{
-                  create<StrideDecoration>(Source{}, 4),
+                  create<StrideDecoration>(4),
               });
-  Alias alias{mod.RegisterSymbol("alias"), "alias", &array};
+  Alias alias{mod->RegisterSymbol("alias"), "alias", &array};
   EXPECT_EQ(16u, alias.BaseAlignment(MemoryLayout::kUniformBuffer));
 }
 
@@ -234,9 +234,9 @@
   U32 u32;
   Array array(&u32, 0,
               ArrayDecorationList{
-                  create<StrideDecoration>(Source{}, 4),
+                  create<StrideDecoration>(4),
               });
-  Alias alias{mod.RegisterSymbol("alias"), "alias", &array};
+  Alias alias{mod->RegisterSymbol("alias"), "alias", &array};
   EXPECT_EQ(16u, alias.BaseAlignment(MemoryLayout::kUniformBuffer));
 }
 
@@ -246,19 +246,19 @@
 
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 0));
-    members.push_back(create<StructMember>(Source{}, "foo", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(0));
+    members.push_back(create<StructMember>("foo", &u32, deco));
   }
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 4));
-    members.push_back(create<StructMember>(Source{}, "bar", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(4));
+    members.push_back(create<StructMember>("bar", &u32, deco));
   }
   StructDecorationList decos;
 
-  auto* str = create<ast::Struct>(Source{}, members, decos);
-  Struct struct_type(mod.RegisterSymbol("struct_type"), "struct_type", str);
-  Alias alias{mod.RegisterSymbol("alias"), "alias", &struct_type};
+  auto* str = create<ast::Struct>(members, decos);
+  Struct struct_type(mod->RegisterSymbol("struct_type"), "struct_type", str);
+  Alias alias{mod->RegisterSymbol("alias"), "alias", &struct_type};
   EXPECT_EQ(16u, alias.BaseAlignment(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(4u, alias.BaseAlignment(MemoryLayout::kStorageBuffer));
 }
diff --git a/src/ast/type/array_type_test.cc b/src/ast/type/array_type_test.cc
index 4de28df..8d61e27 100644
--- a/src/ast/type/array_type_test.cc
+++ b/src/ast/type/array_type_test.cc
@@ -89,8 +89,7 @@
 
 TEST_F(ArrayTest, TypeName_WithStride) {
   I32 i32;
-  Array arr{&i32, 3,
-            ArrayDecorationList{create<StrideDecoration>(Source{}, 16)}};
+  Array arr{&i32, 3, ArrayDecorationList{create<StrideDecoration>(16)}};
   EXPECT_EQ(arr.type_name(), "__array__i32_3_stride_16");
 }
 
@@ -102,30 +101,26 @@
 
 TEST_F(ArrayTest, MinBufferBindingSizeArray) {
   U32 u32;
-  Array arr(&u32, 4,
-            ArrayDecorationList{create<StrideDecoration>(Source{}, 4)});
+  Array arr(&u32, 4, ArrayDecorationList{create<StrideDecoration>(4)});
   EXPECT_EQ(16u, arr.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
 }
 
 TEST_F(ArrayTest, MinBufferBindingSizeRuntimeArray) {
   U32 u32;
-  Array arr(&u32, 0,
-            ArrayDecorationList{create<StrideDecoration>(Source{}, 4)});
+  Array arr(&u32, 0, ArrayDecorationList{create<StrideDecoration>(4)});
   EXPECT_EQ(4u, arr.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
 }
 
 TEST_F(ArrayTest, BaseAlignmentArray) {
   U32 u32;
-  Array arr(&u32, 4,
-            ArrayDecorationList{create<StrideDecoration>(Source{}, 4)});
+  Array arr(&u32, 4, ArrayDecorationList{create<StrideDecoration>(4)});
   EXPECT_EQ(16u, arr.BaseAlignment(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(4u, arr.BaseAlignment(MemoryLayout::kStorageBuffer));
 }
 
 TEST_F(ArrayTest, BaseAlignmentRuntimeArray) {
   U32 u32;
-  Array arr(&u32, 0,
-            ArrayDecorationList{create<StrideDecoration>(Source{}, 4)});
+  Array arr(&u32, 0, ArrayDecorationList{create<StrideDecoration>(4)});
   EXPECT_EQ(16u, arr.BaseAlignment(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(4u, arr.BaseAlignment(MemoryLayout::kStorageBuffer));
 }
diff --git a/src/ast/type/storage_texture_type_test.cc b/src/ast/type/storage_texture_type_test.cc
index 0ed1e51..c47078b 100644
--- a/src/ast/type/storage_texture_type_test.cc
+++ b/src/ast/type/storage_texture_type_test.cc
@@ -92,11 +92,10 @@
 }
 
 TEST_F(StorageTextureTest, F32) {
-  Module mod;
-  Type* s = mod.create<StorageTexture>(TextureDimension::k2dArray,
-                                       ast::AccessControl::kReadOnly,
-                                       ImageFormat::kRgba32Float);
-  TypeDeterminer td(&mod);
+  Type* s = mod->create<StorageTexture>(TextureDimension::k2dArray,
+                                        ast::AccessControl::kReadOnly,
+                                        ImageFormat::kRgba32Float);
+  TypeDeterminer td(mod);
 
   ASSERT_TRUE(td.Determine()) << td.error();
   ASSERT_TRUE(s->Is<Texture>());
@@ -105,11 +104,10 @@
 }
 
 TEST_F(StorageTextureTest, U32) {
-  Module mod;
-  Type* s = mod.create<StorageTexture>(TextureDimension::k2dArray,
-                                       ast::AccessControl::kReadOnly,
-                                       ImageFormat::kRg32Uint);
-  TypeDeterminer td(&mod);
+  Type* s = mod->create<StorageTexture>(TextureDimension::k2dArray,
+                                        ast::AccessControl::kReadOnly,
+                                        ImageFormat::kRg32Uint);
+  TypeDeterminer td(mod);
 
   ASSERT_TRUE(td.Determine()) << td.error();
   ASSERT_TRUE(s->Is<Texture>());
@@ -118,11 +116,10 @@
 }
 
 TEST_F(StorageTextureTest, I32) {
-  Module mod;
-  Type* s = mod.create<StorageTexture>(TextureDimension::k2dArray,
-                                       ast::AccessControl::kReadOnly,
-                                       ImageFormat::kRgba32Sint);
-  TypeDeterminer td(&mod);
+  Type* s = mod->create<StorageTexture>(TextureDimension::k2dArray,
+                                        ast::AccessControl::kReadOnly,
+                                        ImageFormat::kRgba32Sint);
+  TypeDeterminer td(mod);
 
   ASSERT_TRUE(td.Determine()) << td.error();
   ASSERT_TRUE(s->Is<Texture>());
diff --git a/src/ast/type/struct_type_test.cc b/src/ast/type/struct_type_test.cc
index ad1131b..a4d04e6 100644
--- a/src/ast/type/struct_type_test.cc
+++ b/src/ast/type/struct_type_test.cc
@@ -41,18 +41,16 @@
 
 TEST_F(StructTest, Creation) {
   StructMemberList members;
-  auto* impl =
-      create<ast::Struct>(Source{}, members, ast::StructDecorationList{});
+  auto* impl = create<ast::Struct>(members, ast::StructDecorationList{});
   auto* ptr = impl;
-  Struct s{mod.RegisterSymbol("S"), "S", impl};
+  Struct s{mod->RegisterSymbol("S"), "S", impl};
   EXPECT_EQ(s.impl(), ptr);
 }
 
 TEST_F(StructTest, Is) {
   StructMemberList members;
-  auto* impl =
-      create<ast::Struct>(Source{}, members, ast::StructDecorationList{});
-  Struct s{mod.RegisterSymbol("S"), "S", impl};
+  auto* impl = create<ast::Struct>(members, ast::StructDecorationList{});
+  Struct s{mod->RegisterSymbol("S"), "S", impl};
   Type* ty = &s;
   EXPECT_FALSE(ty->Is<AccessControl>());
   EXPECT_FALSE(ty->Is<Alias>());
@@ -71,9 +69,8 @@
 
 TEST_F(StructTest, TypeName) {
   StructMemberList members;
-  auto* impl =
-      create<ast::Struct>(Source{}, members, ast::StructDecorationList{});
-  Struct s{mod.RegisterSymbol("my_struct"), "my_struct", impl};
+  auto* impl = create<ast::Struct>(members, ast::StructDecorationList{});
+  Struct s{mod->RegisterSymbol("my_struct"), "my_struct", impl};
   EXPECT_EQ(s.type_name(), "__struct_tint_symbol_1");
 }
 
@@ -83,18 +80,18 @@
 
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 0));
-    members.push_back(create<StructMember>(Source{}, "foo", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(0));
+    members.push_back(create<StructMember>("foo", &u32, deco));
   }
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 4));
-    members.push_back(create<StructMember>(Source{}, "bar", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(4));
+    members.push_back(create<StructMember>("bar", &u32, deco));
   }
   StructDecorationList decos;
 
-  auto* str = create<ast::Struct>(Source{}, members, decos);
-  Struct struct_type(mod.RegisterSymbol("struct_type"), "struct_type", str);
+  auto* str = create<ast::Struct>(members, decos);
+  Struct struct_type(mod->RegisterSymbol("struct_type"), "struct_type", str);
   EXPECT_EQ(16u,
             struct_type.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(8u, struct_type.MinBufferBindingSize(MemoryLayout::kStorageBuffer));
@@ -102,29 +99,28 @@
 
 TEST_F(StructTest, MinBufferBindingSizeArray) {
   U32 u32;
-  Array arr(&u32, 4,
-            ArrayDecorationList{create<StrideDecoration>(Source{}, 4)});
+  Array arr(&u32, 4, ArrayDecorationList{create<StrideDecoration>(4)});
 
   StructMemberList members;
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 0));
-    members.push_back(create<StructMember>(Source{}, "foo", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(0));
+    members.push_back(create<StructMember>("foo", &u32, deco));
   }
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 4));
-    members.push_back(create<StructMember>(Source{}, "bar", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(4));
+    members.push_back(create<StructMember>("bar", &u32, deco));
   }
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 8));
-    members.push_back(create<StructMember>(Source{}, "bar", &arr, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(8));
+    members.push_back(create<StructMember>("bar", &arr, deco));
   }
   StructDecorationList decos;
 
-  auto* str = create<ast::Struct>(Source{}, members, decos);
-  Struct struct_type(mod.RegisterSymbol("struct_type"), "struct_type", str);
+  auto* str = create<ast::Struct>(members, decos);
+  Struct struct_type(mod->RegisterSymbol("struct_type"), "struct_type", str);
   EXPECT_EQ(32u,
             struct_type.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(24u,
@@ -133,29 +129,28 @@
 
 TEST_F(StructTest, MinBufferBindingSizeRuntimeArray) {
   U32 u32;
-  Array arr(&u32, 0,
-            ArrayDecorationList{create<StrideDecoration>(Source{}, 4)});
+  Array arr(&u32, 0, ArrayDecorationList{create<StrideDecoration>(4)});
 
   StructMemberList members;
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 0));
-    members.push_back(create<StructMember>(Source{}, "foo", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(0));
+    members.push_back(create<StructMember>("foo", &u32, deco));
   }
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 4));
-    members.push_back(create<StructMember>(Source{}, "bar", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(4));
+    members.push_back(create<StructMember>("bar", &u32, deco));
   }
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 8));
-    members.push_back(create<StructMember>(Source{}, "bar", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(8));
+    members.push_back(create<StructMember>("bar", &u32, deco));
   }
   StructDecorationList decos;
 
-  auto* str = create<ast::Struct>(Source{}, members, decos);
-  Struct struct_type(mod.RegisterSymbol("struct_type"), "struct_type", str);
+  auto* str = create<ast::Struct>(members, decos);
+  Struct struct_type(mod->RegisterSymbol("struct_type"), "struct_type", str);
   EXPECT_EQ(12u,
             struct_type.MinBufferBindingSize(MemoryLayout::kStorageBuffer));
 }
@@ -167,13 +162,13 @@
   StructMemberList members;
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 0));
-    members.push_back(create<StructMember>(Source{}, "foo", &vec2, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(0));
+    members.push_back(create<StructMember>("foo", &vec2, deco));
   }
   StructDecorationList decos;
 
-  auto* str = create<ast::Struct>(Source{}, members, decos);
-  Struct struct_type(mod.RegisterSymbol("struct_type"), "struct_type", str);
+  auto* str = create<ast::Struct>(members, decos);
+  Struct struct_type(mod->RegisterSymbol("struct_type"), "struct_type", str);
   EXPECT_EQ(16u,
             struct_type.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(8u, struct_type.MinBufferBindingSize(MemoryLayout::kStorageBuffer));
@@ -186,13 +181,13 @@
   StructMemberList members;
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 0));
-    members.push_back(create<StructMember>(Source{}, "foo", &vec3, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(0));
+    members.push_back(create<StructMember>("foo", &vec3, deco));
   }
   StructDecorationList decos;
 
-  auto* str = create<ast::Struct>(Source{}, members, decos);
-  Struct struct_type(mod.RegisterSymbol("struct_type"), "struct_type", str);
+  auto* str = create<ast::Struct>(members, decos);
+  Struct struct_type(mod->RegisterSymbol("struct_type"), "struct_type", str);
   EXPECT_EQ(16u,
             struct_type.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(16u,
@@ -206,13 +201,13 @@
   StructMemberList members;
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 0));
-    members.push_back(create<StructMember>(Source{}, "foo", &vec4, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(0));
+    members.push_back(create<StructMember>("foo", &vec4, deco));
   }
   StructDecorationList decos;
 
-  auto* str = create<ast::Struct>(Source{}, members, decos);
-  Struct struct_type(mod.RegisterSymbol("struct_type"), "struct_type", str);
+  auto* str = create<ast::Struct>(members, decos);
+  Struct struct_type(mod->RegisterSymbol("struct_type"), "struct_type", str);
   EXPECT_EQ(16u,
             struct_type.MinBufferBindingSize(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(16u,
@@ -225,76 +220,74 @@
 
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 0));
-    members.push_back(create<StructMember>(Source{}, "foo", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(0));
+    members.push_back(create<StructMember>("foo", &u32, deco));
   }
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 4));
-    members.push_back(create<StructMember>(Source{}, "bar", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(4));
+    members.push_back(create<StructMember>("bar", &u32, deco));
   }
   StructDecorationList decos;
 
-  auto* str = create<ast::Struct>(Source{}, members, decos);
-  Struct struct_type(mod.RegisterSymbol("struct_type"), "struct_type", str);
+  auto* str = create<ast::Struct>(members, decos);
+  Struct struct_type(mod->RegisterSymbol("struct_type"), "struct_type", str);
   EXPECT_EQ(16u, struct_type.BaseAlignment(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(4u, struct_type.BaseAlignment(MemoryLayout::kStorageBuffer));
 }
 
 TEST_F(StructTest, BaseAlignmentArray) {
   U32 u32;
-  Array arr(&u32, 4,
-            ArrayDecorationList{create<StrideDecoration>(Source{}, 4)});
+  Array arr(&u32, 4, ArrayDecorationList{create<StrideDecoration>(4)});
 
   StructMemberList members;
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 0));
-    members.push_back(create<StructMember>(Source{}, "foo", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(0));
+    members.push_back(create<StructMember>("foo", &u32, deco));
   }
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 4));
-    members.push_back(create<StructMember>(Source{}, "bar", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(4));
+    members.push_back(create<StructMember>("bar", &u32, deco));
   }
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 8));
-    members.push_back(create<StructMember>(Source{}, "bar", &arr, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(8));
+    members.push_back(create<StructMember>("bar", &arr, deco));
   }
   StructDecorationList decos;
 
-  auto* str = create<ast::Struct>(Source{}, members, decos);
-  Struct struct_type(mod.RegisterSymbol("struct_type"), "struct_type", str);
+  auto* str = create<ast::Struct>(members, decos);
+  Struct struct_type(mod->RegisterSymbol("struct_type"), "struct_type", str);
   EXPECT_EQ(16u, struct_type.BaseAlignment(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(4u, struct_type.BaseAlignment(MemoryLayout::kStorageBuffer));
 }
 
 TEST_F(StructTest, BaseAlignmentRuntimeArray) {
   U32 u32;
-  Array arr(&u32, 0,
-            ArrayDecorationList{create<StrideDecoration>(Source{}, 4)});
+  Array arr(&u32, 0, ArrayDecorationList{create<StrideDecoration>(4)});
 
   StructMemberList members;
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 0));
-    members.push_back(create<StructMember>(Source{}, "foo", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(0));
+    members.push_back(create<StructMember>("foo", &u32, deco));
   }
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 4));
-    members.push_back(create<StructMember>(Source{}, "bar", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(4));
+    members.push_back(create<StructMember>("bar", &u32, deco));
   }
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 8));
-    members.push_back(create<StructMember>(Source{}, "bar", &u32, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(8));
+    members.push_back(create<StructMember>("bar", &u32, deco));
   }
   StructDecorationList decos;
 
-  auto* str = create<ast::Struct>(Source{}, members, decos);
-  Struct struct_type(mod.RegisterSymbol("struct_type"), "struct_type", str);
+  auto* str = create<ast::Struct>(members, decos);
+  Struct struct_type(mod->RegisterSymbol("struct_type"), "struct_type", str);
   EXPECT_EQ(4u, struct_type.BaseAlignment(MemoryLayout::kStorageBuffer));
 }
 
@@ -305,13 +298,13 @@
   StructMemberList members;
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 0));
-    members.push_back(create<StructMember>(Source{}, "foo", &vec2, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(0));
+    members.push_back(create<StructMember>("foo", &vec2, deco));
   }
   StructDecorationList decos;
 
-  auto* str = create<ast::Struct>(Source{}, members, decos);
-  Struct struct_type(mod.RegisterSymbol("struct_type"), "struct_type", str);
+  auto* str = create<ast::Struct>(members, decos);
+  Struct struct_type(mod->RegisterSymbol("struct_type"), "struct_type", str);
   EXPECT_EQ(16u, struct_type.BaseAlignment(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(8u, struct_type.BaseAlignment(MemoryLayout::kStorageBuffer));
 }
@@ -323,13 +316,13 @@
   StructMemberList members;
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 0));
-    members.push_back(create<StructMember>(Source{}, "foo", &vec3, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(0));
+    members.push_back(create<StructMember>("foo", &vec3, deco));
   }
   StructDecorationList decos;
 
-  auto* str = create<ast::Struct>(Source{}, members, decos);
-  Struct struct_type(mod.RegisterSymbol("struct_type"), "struct_type", str);
+  auto* str = create<ast::Struct>(members, decos);
+  Struct struct_type(mod->RegisterSymbol("struct_type"), "struct_type", str);
   EXPECT_EQ(16u, struct_type.BaseAlignment(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(16u, struct_type.BaseAlignment(MemoryLayout::kStorageBuffer));
 }
@@ -341,13 +334,13 @@
   StructMemberList members;
   {
     StructMemberDecorationList deco;
-    deco.push_back(create<StructMemberOffsetDecoration>(Source{}, 0));
-    members.push_back(create<StructMember>(Source{}, "foo", &vec4, deco));
+    deco.push_back(create<StructMemberOffsetDecoration>(0));
+    members.push_back(create<StructMember>("foo", &vec4, deco));
   }
   StructDecorationList decos;
 
-  auto* str = create<ast::Struct>(Source{}, members, decos);
-  Struct struct_type(mod.RegisterSymbol("struct_type"), "struct_type", str);
+  auto* str = create<ast::Struct>(members, decos);
+  Struct struct_type(mod->RegisterSymbol("struct_type"), "struct_type", str);
   EXPECT_EQ(16u, struct_type.BaseAlignment(MemoryLayout::kUniformBuffer));
   EXPECT_EQ(16u, struct_type.BaseAlignment(MemoryLayout::kStorageBuffer));
 }
diff --git a/src/ast/type_constructor_expression_test.cc b/src/ast/type_constructor_expression_test.cc
index f40139a..9b51d8e 100644
--- a/src/ast/type_constructor_expression_test.cc
+++ b/src/ast/type_constructor_expression_test.cc
@@ -30,101 +30,84 @@
 using TypeConstructorExpressionTest = TestHelper;
 
 TEST_F(TypeConstructorExpressionTest, Creation) {
-  type::F32 f32;
   ExpressionList expr;
-  expr.push_back(create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("expr"), "expr"));
+  expr.push_back(Expr("expr"));
 
-  TypeConstructorExpression t(Source{}, &f32, expr);
-  EXPECT_EQ(t.type(), &f32);
-  ASSERT_EQ(t.values().size(), 1u);
-  EXPECT_EQ(t.values()[0], expr[0]);
+  auto* t = create<TypeConstructorExpression>(ty.f32, expr);
+  EXPECT_EQ(t->type(), ty.f32);
+  ASSERT_EQ(t->values().size(), 1u);
+  EXPECT_EQ(t->values()[0], expr[0]);
 }
 
 TEST_F(TypeConstructorExpressionTest, Creation_WithSource) {
-  type::F32 f32;
   ExpressionList expr;
-  expr.push_back(create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("expr"), "expr"));
+  expr.push_back(Expr("expr"));
 
-  TypeConstructorExpression t(Source{Source::Location{20, 2}}, &f32, expr);
-  auto src = t.source();
+  auto* t = create<TypeConstructorExpression>(Source{Source::Location{20, 2}},
+                                              ty.f32, expr);
+  auto src = t->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(TypeConstructorExpressionTest, IsTypeConstructor) {
-  type::F32 f32;
   ExpressionList expr;
-  expr.push_back(create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("expr"), "expr"));
+  expr.push_back(Expr("expr"));
 
-  TypeConstructorExpression t(Source{}, &f32, expr);
-  EXPECT_TRUE(t.Is<TypeConstructorExpression>());
+  auto* t = create<TypeConstructorExpression>(ty.f32, expr);
+  EXPECT_TRUE(t->Is<TypeConstructorExpression>());
 }
 
 TEST_F(TypeConstructorExpressionTest, IsValid) {
-  type::F32 f32;
   ExpressionList expr;
-  expr.push_back(create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("expr"), "expr"));
+  expr.push_back(Expr("expr"));
 
-  TypeConstructorExpression t(Source{}, &f32, expr);
-  EXPECT_TRUE(t.IsValid());
+  auto* t = create<TypeConstructorExpression>(ty.f32, expr);
+  EXPECT_TRUE(t->IsValid());
 }
 
 TEST_F(TypeConstructorExpressionTest, IsValid_EmptyValue) {
-  type::F32 f32;
   ExpressionList expr;
 
-  TypeConstructorExpression t(Source{}, &f32, expr);
-  EXPECT_TRUE(t.IsValid());
+  auto* t = create<TypeConstructorExpression>(ty.f32, expr);
+  EXPECT_TRUE(t->IsValid());
 }
 
 TEST_F(TypeConstructorExpressionTest, IsValid_NullType) {
   ExpressionList expr;
-  expr.push_back(create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("expr"), "expr"));
+  expr.push_back(Expr("expr"));
 
-  TypeConstructorExpression t(Source{}, nullptr, expr);
-  EXPECT_FALSE(t.IsValid());
+  auto* t = create<TypeConstructorExpression>(nullptr, expr);
+  EXPECT_FALSE(t->IsValid());
 }
 
 TEST_F(TypeConstructorExpressionTest, IsValid_NullValue) {
-  type::F32 f32;
   ExpressionList expr;
-  expr.push_back(create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("expr"), "expr"));
+  expr.push_back(Expr("expr"));
   expr.push_back(nullptr);
 
-  TypeConstructorExpression t(Source{}, &f32, expr);
-  EXPECT_FALSE(t.IsValid());
+  auto* t = create<TypeConstructorExpression>(ty.f32, expr);
+  EXPECT_FALSE(t->IsValid());
 }
 
 TEST_F(TypeConstructorExpressionTest, IsValid_InvalidValue) {
-  type::F32 f32;
   ExpressionList expr;
-  expr.push_back(
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol(""), ""));
+  expr.push_back(Expr(""));
 
-  TypeConstructorExpression t(Source{}, &f32, expr);
-  EXPECT_FALSE(t.IsValid());
+  auto* t = create<TypeConstructorExpression>(ty.f32, expr);
+  EXPECT_FALSE(t->IsValid());
 }
 
 TEST_F(TypeConstructorExpressionTest, ToStr) {
-  type::F32 f32;
-  type::Vector vec(&f32, 3);
+  type::Vector vec(ty.f32, 3);
   ExpressionList expr;
-  expr.push_back(create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("expr_1"), "expr_1"));
-  expr.push_back(create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("expr_2"), "expr_2"));
-  expr.push_back(create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("expr_3"), "expr_3"));
+  expr.push_back(Expr("expr_1"));
+  expr.push_back(Expr("expr_2"));
+  expr.push_back(Expr("expr_3"));
 
-  TypeConstructorExpression t(Source{}, &vec, expr);
+  auto* t = create<TypeConstructorExpression>(&vec, expr);
   std::ostringstream out;
-  t.to_str(out, 2);
+  t->to_str(out, 2);
   EXPECT_EQ(demangle(out.str()), R"(  TypeConstructor[not set]{
     __vec_3__f32
     Identifier[not set]{expr_1}
diff --git a/src/ast/uint_literal_test.cc b/src/ast/uint_literal_test.cc
index 6090de1..1197ba7 100644
--- a/src/ast/uint_literal_test.cc
+++ b/src/ast/uint_literal_test.cc
@@ -28,16 +28,13 @@
 using UintLiteralTest = TestHelper;
 
 TEST_F(UintLiteralTest, Value) {
-  type::U32 u32;
-  UintLiteral u{Source{}, &u32, 47};
-  ASSERT_TRUE(u.Is<UintLiteral>());
-  EXPECT_EQ(u.value(), 47u);
+  auto* u = create<UintLiteral>(ty.u32, 47);
+  ASSERT_TRUE(u->Is<UintLiteral>());
+  EXPECT_EQ(u->value(), 47u);
 }
 
 TEST_F(UintLiteralTest, Is) {
-  type::U32 u32;
-  UintLiteral u{Source{}, &u32, 42};
-  Literal* l = &u;
+  ast::Literal* l = create<UintLiteral>(ty.u32, 42);
   EXPECT_FALSE(l->Is<BoolLiteral>());
   EXPECT_FALSE(l->Is<SintLiteral>());
   EXPECT_FALSE(l->Is<FloatLiteral>());
@@ -46,9 +43,8 @@
 }
 
 TEST_F(UintLiteralTest, ToStr) {
-  type::U32 u32;
-  UintLiteral u{Source{}, &u32, 42};
-  EXPECT_EQ(u.to_str(), "42");
+  auto* u = create<UintLiteral>(ty.u32, 42);
+  EXPECT_EQ(u->to_str(), "42");
 }
 
 }  // namespace
diff --git a/src/ast/unary_op_expression_test.cc b/src/ast/unary_op_expression_test.cc
index 10b45ff..9b0717a 100644
--- a/src/ast/unary_op_expression_test.cc
+++ b/src/ast/unary_op_expression_test.cc
@@ -26,55 +26,50 @@
 using UnaryOpExpressionTest = TestHelper;
 
 TEST_F(UnaryOpExpressionTest, Creation) {
-  auto* ident = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("ident"), "ident");
+  auto* ident = Expr("ident");
 
-  UnaryOpExpression u(Source{}, UnaryOp::kNot, ident);
-  EXPECT_EQ(u.op(), UnaryOp::kNot);
-  EXPECT_EQ(u.expr(), ident);
+  auto* u = create<UnaryOpExpression>(UnaryOp::kNot, ident);
+  EXPECT_EQ(u->op(), UnaryOp::kNot);
+  EXPECT_EQ(u->expr(), ident);
 }
 
 TEST_F(UnaryOpExpressionTest, Creation_WithSource) {
-  auto* ident = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("ident"), "ident");
-  UnaryOpExpression u(Source{Source::Location{20, 2}}, UnaryOp::kNot, ident);
-  auto src = u.source();
+  auto* ident = Expr("ident");
+  auto* u = create<UnaryOpExpression>(Source{Source::Location{20, 2}},
+                                      UnaryOp::kNot, ident);
+  auto src = u->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(UnaryOpExpressionTest, IsUnaryOp) {
-  auto* ident = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("ident"), "ident");
-  UnaryOpExpression u(Source{}, UnaryOp::kNot, ident);
-  EXPECT_TRUE(u.Is<UnaryOpExpression>());
+  auto* ident = Expr("ident");
+  auto* u = create<UnaryOpExpression>(UnaryOp::kNot, ident);
+  EXPECT_TRUE(u->Is<UnaryOpExpression>());
 }
 
 TEST_F(UnaryOpExpressionTest, IsValid) {
-  auto* ident = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("ident"), "ident");
-  UnaryOpExpression u(Source{}, UnaryOp::kNot, ident);
-  EXPECT_TRUE(u.IsValid());
+  auto* ident = Expr("ident");
+  auto* u = create<UnaryOpExpression>(UnaryOp::kNot, ident);
+  EXPECT_TRUE(u->IsValid());
 }
 
 TEST_F(UnaryOpExpressionTest, IsValid_NullExpression) {
-  UnaryOpExpression u(Source{}, UnaryOp::kNot, nullptr);
-  EXPECT_FALSE(u.IsValid());
+  auto* u = create<UnaryOpExpression>(UnaryOp::kNot, nullptr);
+  EXPECT_FALSE(u->IsValid());
 }
 
 TEST_F(UnaryOpExpressionTest, IsValid_InvalidExpression) {
-  auto* ident =
-      create<IdentifierExpression>(Source{}, mod.RegisterSymbol(""), "");
-  UnaryOpExpression u(Source{}, UnaryOp::kNot, ident);
-  EXPECT_FALSE(u.IsValid());
+  auto* ident = Expr("");
+  auto* u = create<UnaryOpExpression>(UnaryOp::kNot, ident);
+  EXPECT_FALSE(u->IsValid());
 }
 
 TEST_F(UnaryOpExpressionTest, ToStr) {
-  auto* ident = create<IdentifierExpression>(
-      Source{}, mod.RegisterSymbol("ident"), "ident");
-  UnaryOpExpression u(Source{}, UnaryOp::kNot, ident);
+  auto* ident = Expr("ident");
+  auto* u = create<UnaryOpExpression>(UnaryOp::kNot, ident);
   std::ostringstream out;
-  u.to_str(out, 2);
+  u->to_str(out, 2);
   EXPECT_EQ(demangle(out.str()), R"(  UnaryOp[not set]{
     not
     Identifier[not set]{ident}
diff --git a/src/ast/variable_decl_statement_test.cc b/src/ast/variable_decl_statement_test.cc
index edc7d97..67289f6 100644
--- a/src/ast/variable_decl_statement_test.cc
+++ b/src/ast/variable_decl_statement_test.cc
@@ -25,63 +25,53 @@
 using VariableDeclStatementTest = TestHelper;
 
 TEST_F(VariableDeclStatementTest, Creation) {
-  type::F32 f32;
-  auto* var = create<Variable>(Source{}, "a", StorageClass::kNone, &f32, false,
-                               nullptr, ast::VariableDecorationList{});
+  auto* var = Var("a", StorageClass::kNone, ty.f32);
 
-  VariableDeclStatement stmt(Source{}, var);
-  EXPECT_EQ(stmt.variable(), var);
+  auto* stmt = create<VariableDeclStatement>(var);
+  EXPECT_EQ(stmt->variable(), var);
 }
 
 TEST_F(VariableDeclStatementTest, Creation_WithSource) {
-  type::F32 f32;
-  auto* var = create<Variable>(Source{}, "a", StorageClass::kNone, &f32, false,
-                               nullptr, ast::VariableDecorationList{});
+  auto* var = Var("a", StorageClass::kNone, ty.f32);
 
-  VariableDeclStatement stmt(Source{Source::Location{20, 2}}, var);
-  auto src = stmt.source();
+  auto* stmt =
+      create<VariableDeclStatement>(Source{Source::Location{20, 2}}, var);
+  auto src = stmt->source();
   EXPECT_EQ(src.range.begin.line, 20u);
   EXPECT_EQ(src.range.begin.column, 2u);
 }
 
 TEST_F(VariableDeclStatementTest, IsVariableDecl) {
-  type::F32 f32;
-  auto* var = create<Variable>(Source{}, "a", StorageClass::kNone, &f32, false,
-                               nullptr, ast::VariableDecorationList{});
+  auto* var = Var("a", StorageClass::kNone, ty.f32);
 
-  VariableDeclStatement stmt(Source{}, var);
-  EXPECT_TRUE(stmt.Is<VariableDeclStatement>());
+  auto* stmt = create<VariableDeclStatement>(var);
+  EXPECT_TRUE(stmt->Is<VariableDeclStatement>());
 }
 
 TEST_F(VariableDeclStatementTest, IsValid) {
-  type::F32 f32;
-  auto* var = create<Variable>(Source{}, "a", StorageClass::kNone, &f32, false,
-                               nullptr, ast::VariableDecorationList{});
-  VariableDeclStatement stmt(Source{}, var);
-  EXPECT_TRUE(stmt.IsValid());
+  auto* var = Var("a", StorageClass::kNone, ty.f32);
+  auto* stmt = create<VariableDeclStatement>(var);
+  EXPECT_TRUE(stmt->IsValid());
 }
 
 TEST_F(VariableDeclStatementTest, IsValid_InvalidVariable) {
-  type::F32 f32;
-  auto* var = create<Variable>(Source{}, "", StorageClass::kNone, &f32, false,
-                               nullptr, ast::VariableDecorationList{});
-  VariableDeclStatement stmt(Source{}, var);
-  EXPECT_FALSE(stmt.IsValid());
+  auto* var = Var("", StorageClass::kNone, ty.f32);
+  auto* stmt = create<VariableDeclStatement>(var);
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(VariableDeclStatementTest, IsValid_NullVariable) {
-  VariableDeclStatement stmt(Source{}, nullptr);
-  EXPECT_FALSE(stmt.IsValid());
+  auto* stmt = create<VariableDeclStatement>(nullptr);
+  EXPECT_FALSE(stmt->IsValid());
 }
 
 TEST_F(VariableDeclStatementTest, ToStr) {
-  type::F32 f32;
-  auto* var = create<Variable>(Source{}, "a", StorageClass::kNone, &f32, false,
-                               nullptr, ast::VariableDecorationList{});
+  auto* var = Var("a", StorageClass::kNone, ty.f32);
 
-  VariableDeclStatement stmt(Source{Source::Location{20, 2}}, var);
+  auto* stmt =
+      create<VariableDeclStatement>(Source{Source::Location{20, 2}}, var);
   std::ostringstream out;
-  stmt.to_str(out, 2);
+  stmt->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(  VariableDeclStatement{
     Variable{
       a
diff --git a/src/ast/variable_test.cc b/src/ast/variable_test.cc
index 778b4b7..3004d31 100644
--- a/src/ast/variable_test.cc
+++ b/src/ast/variable_test.cc
@@ -27,106 +27,83 @@
 using VariableTest = TestHelper;
 
 TEST_F(VariableTest, Creation) {
-  type::I32 t;
-  Variable v(Source{}, "my_var", StorageClass::kFunction, &t, false, nullptr,
-             ast::VariableDecorationList{});
+  auto* v = Var("my_var", StorageClass::kFunction, ty.i32);
 
-  EXPECT_EQ(v.name(), "my_var");
-  EXPECT_EQ(v.storage_class(), StorageClass::kFunction);
-  EXPECT_EQ(v.type(), &t);
-  EXPECT_EQ(v.source().range.begin.line, 0u);
-  EXPECT_EQ(v.source().range.begin.column, 0u);
-  EXPECT_EQ(v.source().range.end.line, 0u);
-  EXPECT_EQ(v.source().range.end.column, 0u);
+  EXPECT_EQ(v->name(), "my_var");
+  EXPECT_EQ(v->storage_class(), StorageClass::kFunction);
+  EXPECT_EQ(v->type(), ty.i32);
+  EXPECT_EQ(v->source().range.begin.line, 0u);
+  EXPECT_EQ(v->source().range.begin.column, 0u);
+  EXPECT_EQ(v->source().range.end.line, 0u);
+  EXPECT_EQ(v->source().range.end.column, 0u);
 }
 
 TEST_F(VariableTest, CreationWithSource) {
-  Source s{Source::Range{Source::Location{27, 4}, Source::Location{27, 5}}};
-  type::F32 t;
-  Variable v(s, "i", StorageClass::kPrivate, &t, false, nullptr,
-             ast::VariableDecorationList{});
+  auto* v = Var(
+      Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 5}}},
+      "i", StorageClass::kPrivate, ty.f32, nullptr, VariableDecorationList{});
 
-  EXPECT_EQ(v.name(), "i");
-  EXPECT_EQ(v.storage_class(), StorageClass::kPrivate);
-  EXPECT_EQ(v.type(), &t);
-  EXPECT_EQ(v.source().range.begin.line, 27u);
-  EXPECT_EQ(v.source().range.begin.column, 4u);
-  EXPECT_EQ(v.source().range.end.line, 27u);
-  EXPECT_EQ(v.source().range.end.column, 5u);
+  EXPECT_EQ(v->name(), "i");
+  EXPECT_EQ(v->storage_class(), StorageClass::kPrivate);
+  EXPECT_EQ(v->type(), ty.f32);
+  EXPECT_EQ(v->source().range.begin.line, 27u);
+  EXPECT_EQ(v->source().range.begin.column, 4u);
+  EXPECT_EQ(v->source().range.end.line, 27u);
+  EXPECT_EQ(v->source().range.end.column, 5u);
 }
 
 TEST_F(VariableTest, CreationEmpty) {
-  type::I32 t;
-  Source s{Source::Range{Source::Location{27, 4}, Source::Location{27, 7}}};
-  Variable v(s, "a_var", StorageClass::kWorkgroup, &t, false, nullptr,
-             ast::VariableDecorationList{});
+  auto* v = Var(
+      Source{Source::Range{Source::Location{27, 4}, Source::Location{27, 7}}},
+      "a_var", StorageClass::kWorkgroup, ty.i32, nullptr,
+      VariableDecorationList{});
 
-  EXPECT_EQ(v.name(), "a_var");
-  EXPECT_EQ(v.storage_class(), StorageClass::kWorkgroup);
-  EXPECT_EQ(v.type(), &t);
-  EXPECT_EQ(v.source().range.begin.line, 27u);
-  EXPECT_EQ(v.source().range.begin.column, 4u);
-  EXPECT_EQ(v.source().range.end.line, 27u);
-  EXPECT_EQ(v.source().range.end.column, 7u);
+  EXPECT_EQ(v->name(), "a_var");
+  EXPECT_EQ(v->storage_class(), StorageClass::kWorkgroup);
+  EXPECT_EQ(v->type(), ty.i32);
+  EXPECT_EQ(v->source().range.begin.line, 27u);
+  EXPECT_EQ(v->source().range.begin.column, 4u);
+  EXPECT_EQ(v->source().range.end.line, 27u);
+  EXPECT_EQ(v->source().range.end.column, 7u);
 }
 
 TEST_F(VariableTest, IsValid) {
-  type::I32 t;
-  Variable v{Source{}, "my_var", StorageClass::kNone,          &t,
-             false,    nullptr,  ast::VariableDecorationList{}};
-  EXPECT_TRUE(v.IsValid());
+  auto* v = Var("my_var", StorageClass::kNone, ty.i32);
+  EXPECT_TRUE(v->IsValid());
 }
 
 TEST_F(VariableTest, IsValid_WithConstructor) {
-  type::I32 t;
-  Variable v{Source{},
-             "my_var",
-             StorageClass::kNone,
-             &t,
-             false,
-             create<IdentifierExpression>(Source{}, mod.RegisterSymbol("ident"),
-                                          "ident"),
-             ast::VariableDecorationList{}};
-  EXPECT_TRUE(v.IsValid());
+  auto* v = Var("my_var", StorageClass::kNone, ty.i32, Expr("ident"),
+                ast::VariableDecorationList{});
+  EXPECT_TRUE(v->IsValid());
 }
 
 TEST_F(VariableTest, IsValid_MissinName) {
-  type::I32 t;
-  Variable v{Source{}, "",      StorageClass::kNone,          &t,
-             false,    nullptr, ast::VariableDecorationList{}};
-  EXPECT_FALSE(v.IsValid());
+  auto* v = Var("", StorageClass::kNone, ty.i32);
+  EXPECT_FALSE(v->IsValid());
 }
 
 TEST_F(VariableTest, IsValid_MissingType) {
-  Variable v{Source{}, "x",     StorageClass::kNone,          nullptr,
-             false,    nullptr, ast::VariableDecorationList{}};
-  EXPECT_FALSE(v.IsValid());
+  auto* v = Var("x", StorageClass::kNone, nullptr);
+  EXPECT_FALSE(v->IsValid());
 }
 
 TEST_F(VariableTest, IsValid_MissingBoth) {
-  Variable v{Source{}, "",      StorageClass::kNone,          nullptr,
-             false,    nullptr, ast::VariableDecorationList{}};
-  EXPECT_FALSE(v.IsValid());
+  auto* v = Var("", StorageClass::kNone, nullptr);
+  EXPECT_FALSE(v->IsValid());
 }
 
 TEST_F(VariableTest, IsValid_InvalidConstructor) {
-  type::I32 t;
-  Variable v{Source{},
-             "my_var",
-             StorageClass::kNone,
-             &t,
-             false,
-             create<IdentifierExpression>(Source{}, mod.RegisterSymbol(""), ""),
-             ast::VariableDecorationList{}};
-  EXPECT_FALSE(v.IsValid());
+  auto* v = Var("my_var", StorageClass::kNone, ty.i32, Expr(""),
+                ast::VariableDecorationList{});
+  EXPECT_FALSE(v->IsValid());
 }
 
 TEST_F(VariableTest, to_str) {
-  type::F32 t;
-  Variable v{Source{}, "my_var", StorageClass::kFunction,      &t,
-             false,    nullptr,  ast::VariableDecorationList{}};
+  auto* v = Var("my_var", StorageClass::kFunction, ty.f32, nullptr,
+                ast::VariableDecorationList{});
   std::ostringstream out;
-  v.to_str(out, 2);
+  v->to_str(out, 2);
   EXPECT_EQ(out.str(), R"(  Variable{
     my_var
     function
@@ -136,14 +113,12 @@
 }
 
 TEST_F(VariableTest, WithDecorations) {
-  type::F32 t;
-  auto* var = create<Variable>(
-      Source{}, "my_var", StorageClass::kFunction, &t, false, nullptr,
-      VariableDecorationList{
-          create<LocationDecoration>(Source{}, 1),
-          create<BuiltinDecoration>(Source{}, Builtin::kPosition),
-          create<ConstantIdDecoration>(Source{}, 1200),
-      });
+  auto* var = Var("my_var", StorageClass::kFunction, ty.i32, nullptr,
+                  VariableDecorationList{
+                      create<LocationDecoration>(1),
+                      create<BuiltinDecoration>(Builtin::kPosition),
+                      create<ConstantIdDecoration>(1200),
+                  });
 
   EXPECT_TRUE(var->HasLocationDecoration());
   EXPECT_TRUE(var->HasBuiltinDecoration());
@@ -151,26 +126,20 @@
 }
 
 TEST_F(VariableTest, ConstantId) {
-  type::F32 t;
-  auto* var = create<Variable>(Source{}, "my_var", StorageClass::kFunction, &t,
-                               false, nullptr,
-                               VariableDecorationList{
-                                   create<ConstantIdDecoration>(Source{}, 1200),
-                               });
+  auto* var = Var("my_var", StorageClass::kFunction, ty.i32, nullptr,
+                  VariableDecorationList{
+                      create<ConstantIdDecoration>(1200),
+                  });
 
   EXPECT_EQ(var->constant_id(), 1200u);
 }
 
 TEST_F(VariableTest, Decorated_to_str) {
-  type::F32 t;
-  auto* var =
-      create<Variable>(Source{}, "my_var", StorageClass::kFunction, &t, false,
-                       create<IdentifierExpression>(
-                           Source{}, mod.RegisterSymbol("expr"), "expr"),
-                       VariableDecorationList{
-                           create<BindingDecoration>(Source{}, 2),
-                           create<SetDecoration>(Source{}, 1),
-                       });
+  auto* var = Var("my_var", StorageClass::kFunction, ty.f32, Expr("expr"),
+                  VariableDecorationList{
+                      create<BindingDecoration>(2),
+                      create<SetDecoration>(1),
+                  });
 
   std::ostringstream out;
   var->to_str(out, 2);
diff --git a/src/ast/workgroup_decoration_test.cc b/src/ast/workgroup_decoration_test.cc
index b45dff8..4a749f1 100644
--- a/src/ast/workgroup_decoration_test.cc
+++ b/src/ast/workgroup_decoration_test.cc
@@ -26,48 +26,47 @@
 using WorkgroupDecorationTest = TestHelper;
 
 TEST_F(WorkgroupDecorationTest, Creation_1param) {
-  WorkgroupDecoration d{Source{}, 2};
+  auto* d = create<WorkgroupDecoration>(2);
   uint32_t x = 0;
   uint32_t y = 0;
   uint32_t z = 0;
-  std::tie(x, y, z) = d.values();
+  std::tie(x, y, z) = d->values();
   EXPECT_EQ(x, 2u);
   EXPECT_EQ(y, 1u);
   EXPECT_EQ(z, 1u);
 }
 TEST_F(WorkgroupDecorationTest, Creation_2param) {
-  WorkgroupDecoration d{Source{}, 2, 4};
+  auto* d = create<WorkgroupDecoration>(2, 4);
   uint32_t x = 0;
   uint32_t y = 0;
   uint32_t z = 0;
-  std::tie(x, y, z) = d.values();
+  std::tie(x, y, z) = d->values();
   EXPECT_EQ(x, 2u);
   EXPECT_EQ(y, 4u);
   EXPECT_EQ(z, 1u);
 }
 
 TEST_F(WorkgroupDecorationTest, Creation_3param) {
-  WorkgroupDecoration d{Source{}, 2, 4, 6};
+  auto* d = create<WorkgroupDecoration>(2, 4, 6);
   uint32_t x = 0;
   uint32_t y = 0;
   uint32_t z = 0;
-  std::tie(x, y, z) = d.values();
+  std::tie(x, y, z) = d->values();
   EXPECT_EQ(x, 2u);
   EXPECT_EQ(y, 4u);
   EXPECT_EQ(z, 6u);
 }
 
 TEST_F(WorkgroupDecorationTest, Is) {
-  WorkgroupDecoration wd{Source{}, 2, 4, 6};
-  Decoration* d = &wd;
+  Decoration* d = create<WorkgroupDecoration>(2, 4, 6);
   EXPECT_TRUE(d->Is<WorkgroupDecoration>());
   EXPECT_FALSE(d->Is<StageDecoration>());
 }
 
 TEST_F(WorkgroupDecorationTest, ToStr) {
-  WorkgroupDecoration d{Source{}, 2, 4, 6};
+  auto* d = create<WorkgroupDecoration>(2, 4, 6);
   std::ostringstream out;
-  d.to_str(out, 0);
+  d->to_str(out, 0);
   EXPECT_EQ(out.str(), R"(WorkgroupDecoration{2 4 6}
 )");
 }