Move pointer and ref to type/

This CL moves the pointer and reference files over to type/ and updates
the namespaces.

Bug: tint:1718
Change-Id: I487a37ef2f6a3884d2ff51af4ac63869c3e03698
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/113420
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index 77e65d1..c1aeef0 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -439,8 +439,6 @@
     "sem/node.h",
     "sem/parameter_usage.h",
     "sem/pipeline_stage_set.h",
-    "sem/pointer.h",
-    "sem/reference.h",
     "sem/sampler_texture_pair.h",
     "sem/struct.h",
     "sem/switch_statement.h",
@@ -572,6 +570,8 @@
     "type/i32.h",
     "type/multisampled_texture.h",
     "type/node.h",
+    "type/pointer.h",
+    "type/reference.h",
     "type/sampled_texture.h",
     "type/sampler.h",
     "type/storage_texture.h",
@@ -681,10 +681,6 @@
     "sem/parameter_usage.cc",
     "sem/parameter_usage.h",
     "sem/pipeline_stage_set.h",
-    "sem/pointer.cc",
-    "sem/pointer.h",
-    "sem/reference.cc",
-    "sem/reference.h",
     "sem/statement.cc",
     "sem/struct.cc",
     "sem/struct.h",
@@ -733,6 +729,10 @@
     "type/multisampled_texture.h",
     "type/node.cc",
     "type/node.h",
+    "type/pointer.cc",
+    "type/pointer.h",
+    "type/reference.cc",
+    "type/reference.h",
     "type/sampled_texture.cc",
     "type/sampled_texture.h",
     "type/sampler.cc",
@@ -1207,8 +1207,6 @@
       "sem/builtin_test.cc",
       "sem/expression_test.cc",
       "sem/matrix_test.cc",
-      "sem/pointer_test.cc",
-      "sem/reference_test.cc",
       "sem/struct_test.cc",
       "sem/vector_test.cc",
     ]
@@ -1224,6 +1222,8 @@
       "type/f32_test.cc",
       "type/i32_test.cc",
       "type/multisampled_texture_test.cc",
+      "type/pointer_test.cc",
+      "type/reference_test.cc",
       "type/sampled_texture_test.cc",
       "type/sampler_test.cc",
       "type/storage_texture_test.cc",
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index bb6ff5f..827b055 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -336,10 +336,6 @@
   sem/node.cc
   sem/node.h
   sem/pipeline_stage_set.h
-  sem/pointer.cc
-  sem/pointer.h
-  sem/reference.cc
-  sem/reference.h
   sem/sampler_texture_pair.h
   sem/statement.cc
   sem/struct.cc
@@ -489,6 +485,10 @@
   type/multisampled_texture.h
   type/node.cc
   type/node.h
+  type/pointer.cc
+  type/pointer.h
+  type/reference.cc
+  type/reference.h
   type/sampled_texture.cc
   type/sampled_texture.h
   type/sampler.cc
@@ -925,8 +925,6 @@
     sem/builtin_test.cc
     sem/expression_test.cc
     sem/matrix_test.cc
-    sem/pointer_test.cc
-    sem/reference_test.cc
     sem/struct_test.cc
     sem/vector_test.cc
     source_test.cc
@@ -944,6 +942,8 @@
     type/f32_test.cc
     type/i32_test.cc
     type/multisampled_texture_test.cc
+    type/pointer_test.cc
+    type/reference_test.cc
     type/sampled_texture_test.cc
     type/sampler_test.cc
     type/storage_texture_test.cc
diff --git a/src/tint/fuzzers/tint_ast_fuzzer/mutation_finders/change_unary_operators.cc b/src/tint/fuzzers/tint_ast_fuzzer/mutation_finders/change_unary_operators.cc
index 16e0ab3..adcf71f 100644
--- a/src/tint/fuzzers/tint_ast_fuzzer/mutation_finders/change_unary_operators.cc
+++ b/src/tint/fuzzers/tint_ast_fuzzer/mutation_finders/change_unary_operators.cc
@@ -19,7 +19,7 @@
 #include "src/tint/ast/unary_op_expression.h"
 #include "src/tint/fuzzers/tint_ast_fuzzer/mutations/change_unary_operator.h"
 #include "src/tint/fuzzers/tint_ast_fuzzer/util.h"
-#include "src/tint/sem/reference.h"
+#include "src/tint/type/reference.h"
 
 namespace tint::fuzzers::ast_fuzzer {
 
@@ -43,7 +43,7 @@
         // Get the type of the unary expression.
         const auto* type = program.Sem().Get(unary_expr)->Type();
         const auto* basic_type =
-            type->Is<sem::Reference>() ? type->As<sem::Reference>()->StoreType() : type;
+            type->Is<type::Reference>() ? type->As<type::Reference>()->StoreType() : type;
 
         // Only signed integer or vector of signed integer can be mutated.
         if (!basic_type->is_signed_integer_scalar_or_vector()) {
diff --git a/src/tint/fuzzers/tint_ast_fuzzer/mutations/change_binary_operator.cc b/src/tint/fuzzers/tint_ast_fuzzer/mutations/change_binary_operator.cc
index aa46ec3..78cc131 100644
--- a/src/tint/fuzzers/tint_ast_fuzzer/mutations/change_binary_operator.cc
+++ b/src/tint/fuzzers/tint_ast_fuzzer/mutations/change_binary_operator.cc
@@ -17,8 +17,8 @@
 #include <utility>
 
 #include "src/tint/program_builder.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/type/bool.h"
+#include "src/tint/type/reference.h"
 
 namespace tint::fuzzers::ast_fuzzer {
 
@@ -302,9 +302,9 @@
 
     // If these are reference types, unwrap them to get the pointee type.
     const type::Type* lhs_basic_type =
-        lhs_type->Is<sem::Reference>() ? lhs_type->As<sem::Reference>()->StoreType() : lhs_type;
+        lhs_type->Is<type::Reference>() ? lhs_type->As<type::Reference>()->StoreType() : lhs_type;
     const type::Type* rhs_basic_type =
-        rhs_type->Is<sem::Reference>() ? rhs_type->As<sem::Reference>()->StoreType() : rhs_type;
+        rhs_type->Is<type::Reference>() ? rhs_type->As<type::Reference>()->StoreType() : rhs_type;
 
     switch (binary_expr.op) {
         case ast::BinaryOp::kAdd:
diff --git a/src/tint/fuzzers/tint_ast_fuzzer/mutations/change_unary_operator.cc b/src/tint/fuzzers/tint_ast_fuzzer/mutations/change_unary_operator.cc
index c9bed06..f42ec92 100644
--- a/src/tint/fuzzers/tint_ast_fuzzer/mutations/change_unary_operator.cc
+++ b/src/tint/fuzzers/tint_ast_fuzzer/mutations/change_unary_operator.cc
@@ -18,7 +18,7 @@
 
 #include "src/tint/fuzzers/tint_ast_fuzzer/util.h"
 #include "src/tint/program_builder.h"
-#include "src/tint/sem/reference.h"
+#include "src/tint/type/reference.h"
 
 namespace tint::fuzzers::ast_fuzzer {
 
@@ -48,7 +48,7 @@
     // Get the type of the unary expression.
     const auto* type = program.Sem().Get(unary_expr_node)->Type();
     const auto* basic_type =
-        type->Is<sem::Reference>() ? type->As<sem::Reference>()->StoreType() : type;
+        type->Is<type::Reference>() ? type->As<type::Reference>()->StoreType() : type;
 
     // Only signed integer or vector of signed integer has more than 1
     // unary operators to change between.
diff --git a/src/tint/program_builder.h b/src/tint/program_builder.h
index 4312528..83cb18f 100644
--- a/src/tint/program_builder.h
+++ b/src/tint/program_builder.h
@@ -94,7 +94,6 @@
 #include "src/tint/sem/array_count.h"
 #include "src/tint/sem/constant.h"
 #include "src/tint/sem/matrix.h"
-#include "src/tint/sem/pointer.h"
 #include "src/tint/sem/struct.h"
 #include "src/tint/sem/vector.h"
 #include "src/tint/type/bool.h"
@@ -104,6 +103,7 @@
 #include "src/tint/type/f32.h"
 #include "src/tint/type/i32.h"
 #include "src/tint/type/multisampled_texture.h"
+#include "src/tint/type/pointer.h"
 #include "src/tint/type/sampled_texture.h"
 #include "src/tint/type/storage_texture.h"
 #include "src/tint/type/u32.h"
diff --git a/src/tint/resolver/array_accessor_test.cc b/src/tint/resolver/array_accessor_test.cc
index 2a95c39..a41c00b 100644
--- a/src/tint/resolver/array_accessor_test.cc
+++ b/src/tint/resolver/array_accessor_test.cc
@@ -17,7 +17,7 @@
 #include "gmock/gmock.h"
 #include "src/tint/resolver/resolver_test_helper.h"
 #include "src/tint/sem/index_accessor_expression.h"
-#include "src/tint/sem/reference.h"
+#include "src/tint/type/reference.h"
 
 using namespace tint::number_suffixes;  // NOLINT
 
@@ -108,9 +108,9 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(acc), nullptr);
-    ASSERT_TRUE(TypeOf(acc)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(acc)->Is<type::Reference>());
 
-    auto* ref = TypeOf(acc)->As<sem::Reference>();
+    auto* ref = TypeOf(acc)->As<type::Reference>();
     ASSERT_TRUE(ref->StoreType()->Is<sem::Vector>());
     EXPECT_EQ(ref->StoreType()->As<sem::Vector>()->Width(), 3u);
 
@@ -129,9 +129,9 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(acc), nullptr);
-    ASSERT_TRUE(TypeOf(acc)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(acc)->Is<type::Reference>());
 
-    auto* ref = TypeOf(acc)->As<sem::Reference>();
+    auto* ref = TypeOf(acc)->As<type::Reference>();
     EXPECT_TRUE(ref->StoreType()->Is<type::F32>());
 
     auto idx_sem = Sem().Get<sem::IndexAccessorExpression>(acc);
@@ -181,9 +181,9 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(acc), nullptr);
-    ASSERT_TRUE(TypeOf(acc)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(acc)->Is<type::Reference>());
 
-    auto* ref = TypeOf(acc)->As<sem::Reference>();
+    auto* ref = TypeOf(acc)->As<type::Reference>();
     EXPECT_TRUE(ref->StoreType()->Is<type::F32>());
 
     auto idx_sem = Sem().Get<sem::IndexAccessorExpression>(acc);
@@ -198,7 +198,7 @@
     WrapInFunction(acc);
     EXPECT_TRUE(r()->Resolve()) << r()->error();
     ASSERT_NE(TypeOf(acc), nullptr);
-    auto* ref = TypeOf(acc)->As<sem::Reference>();
+    auto* ref = TypeOf(acc)->As<type::Reference>();
     ASSERT_NE(ref, nullptr);
     EXPECT_TRUE(ref->StoreType()->Is<type::F32>());
 
@@ -214,7 +214,7 @@
     WrapInFunction(acc);
     EXPECT_TRUE(r()->Resolve()) << r()->error();
     ASSERT_NE(TypeOf(acc), nullptr);
-    auto* ref = TypeOf(acc)->As<sem::Reference>();
+    auto* ref = TypeOf(acc)->As<type::Reference>();
     ASSERT_NE(ref, nullptr);
     EXPECT_TRUE(ref->StoreType()->Is<type::F32>());
 
@@ -230,7 +230,7 @@
     WrapInFunction(acc);
     EXPECT_TRUE(r()->Resolve()) << r()->error();
     ASSERT_NE(TypeOf(acc), nullptr);
-    auto* ref = TypeOf(acc)->As<sem::Reference>();
+    auto* ref = TypeOf(acc)->As<type::Reference>();
     ASSERT_NE(ref, nullptr);
     EXPECT_TRUE(ref->StoreType()->Is<type::F32>());
 
@@ -251,9 +251,9 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(acc), nullptr);
-    ASSERT_TRUE(TypeOf(acc)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(acc)->Is<type::Reference>());
 
-    auto* ref = TypeOf(acc)->As<sem::Reference>();
+    auto* ref = TypeOf(acc)->As<type::Reference>();
     EXPECT_TRUE(ref->StoreType()->Is<type::F32>());
 
     auto idx_sem = Sem().Get<sem::IndexAccessorExpression>(acc);
diff --git a/src/tint/resolver/atomics_test.cc b/src/tint/resolver/atomics_test.cc
index e4851bb..ac0de88 100644
--- a/src/tint/resolver/atomics_test.cc
+++ b/src/tint/resolver/atomics_test.cc
@@ -15,7 +15,7 @@
 #include "src/tint/resolver/resolver.h"
 #include "src/tint/resolver/resolver_test_helper.h"
 #include "src/tint/sem/atomic.h"
-#include "src/tint/sem/reference.h"
+#include "src/tint/type/reference.h"
 
 #include "gmock/gmock.h"
 
@@ -30,7 +30,7 @@
     auto* g = GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.i32()), ast::AddressSpace::kWorkgroup);
 
     EXPECT_TRUE(r()->Resolve()) << r()->error();
-    ASSERT_TRUE(TypeOf(g)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(g)->Is<type::Reference>());
     auto* atomic = TypeOf(g)->UnwrapRef()->As<sem::Atomic>();
     ASSERT_NE(atomic, nullptr);
     EXPECT_TRUE(atomic->Type()->Is<type::I32>());
@@ -40,7 +40,7 @@
     auto* g = GlobalVar("a", ty.atomic(Source{{12, 34}}, ty.u32()), ast::AddressSpace::kWorkgroup);
 
     EXPECT_TRUE(r()->Resolve()) << r()->error();
-    ASSERT_TRUE(TypeOf(g)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(g)->Is<type::Reference>());
     auto* atomic = TypeOf(g)->UnwrapRef()->As<sem::Atomic>();
     ASSERT_NE(atomic, nullptr);
     EXPECT_TRUE(atomic->Type()->Is<type::U32>());
@@ -52,7 +52,7 @@
                         Binding(0_a), Group(0_a));
 
     EXPECT_TRUE(r()->Resolve()) << r()->error();
-    ASSERT_TRUE(TypeOf(g)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(g)->Is<type::Reference>());
     auto* str = TypeOf(g)->UnwrapRef()->As<sem::Struct>();
     ASSERT_NE(str, nullptr);
     ASSERT_EQ(str->Members().Length(), 1u);
diff --git a/src/tint/resolver/atomics_validation_test.cc b/src/tint/resolver/atomics_validation_test.cc
index 8b79941..afc44c9 100644
--- a/src/tint/resolver/atomics_validation_test.cc
+++ b/src/tint/resolver/atomics_validation_test.cc
@@ -15,7 +15,7 @@
 #include "src/tint/resolver/resolver.h"
 #include "src/tint/resolver/resolver_test_helper.h"
 #include "src/tint/sem/atomic.h"
-#include "src/tint/sem/reference.h"
+#include "src/tint/type/reference.h"
 
 #include "gmock/gmock.h"
 
diff --git a/src/tint/resolver/intrinsic_table.cc b/src/tint/resolver/intrinsic_table.cc
index 0546561..660845d 100644
--- a/src/tint/resolver/intrinsic_table.cc
+++ b/src/tint/resolver/intrinsic_table.cc
@@ -549,7 +549,7 @@
         return true;
     }
 
-    if (auto* p = ty->As<sem::Pointer>()) {
+    if (auto* p = ty->As<type::Pointer>()) {
         S = Number(static_cast<uint32_t>(p->AddressSpace()));
         T = p->StoreType();
         A = Number(static_cast<uint32_t>(p->Access()));
@@ -558,9 +558,9 @@
     return false;
 }
 
-const sem::Pointer* build_ptr(MatchState& state, Number S, const type::Type* T, Number& A) {
-    return state.builder.create<sem::Pointer>(T, static_cast<ast::AddressSpace>(S.Value()),
-                                              static_cast<ast::Access>(A.Value()));
+const type::Pointer* build_ptr(MatchState& state, Number S, const type::Type* T, Number& A) {
+    return state.builder.create<type::Pointer>(T, static_cast<ast::AddressSpace>(S.Value()),
+                                               static_cast<ast::Access>(A.Value()));
 }
 
 bool match_atomic(MatchState&, const type::Type* ty, const type::Type*& T) {
diff --git a/src/tint/resolver/intrinsic_table_test.cc b/src/tint/resolver/intrinsic_table_test.cc
index 6f984a1..4d468fa 100644
--- a/src/tint/resolver/intrinsic_table_test.cc
+++ b/src/tint/resolver/intrinsic_table_test.cc
@@ -20,13 +20,13 @@
 #include "src/tint/program_builder.h"
 #include "src/tint/resolver/resolver_test_helper.h"
 #include "src/tint/sem/atomic.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/sem/type_conversion.h"
 #include "src/tint/sem/type_initializer.h"
 #include "src/tint/type/depth_multisampled_texture.h"
 #include "src/tint/type/depth_texture.h"
 #include "src/tint/type/external_texture.h"
 #include "src/tint/type/multisampled_texture.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/type/sampled_texture.h"
 #include "src/tint/type/storage_texture.h"
 #include "src/tint/type/test_helper.h"
@@ -231,7 +231,7 @@
     auto* i32 = create<type::I32>();
     auto* atomicI32 = create<sem::Atomic>(i32);
     auto* ptr =
-        create<sem::Pointer>(atomicI32, ast::AddressSpace::kWorkgroup, ast::Access::kReadWrite);
+        create<type::Pointer>(atomicI32, ast::AddressSpace::kWorkgroup, ast::Access::kReadWrite);
     auto result = table->Lookup(BuiltinType::kAtomicLoad, utils::Vector{ptr},
                                 sem::EvaluationStage::kConstant, Source{});
     ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
@@ -254,7 +254,8 @@
 TEST_F(IntrinsicTableTest, MatchArray) {
     auto* arr =
         create<sem::Array>(create<type::U32>(), create<type::RuntimeArrayCount>(), 4u, 4u, 4u, 4u);
-    auto* arr_ptr = create<sem::Pointer>(arr, ast::AddressSpace::kStorage, ast::Access::kReadWrite);
+    auto* arr_ptr =
+        create<type::Pointer>(arr, ast::AddressSpace::kStorage, ast::Access::kReadWrite);
     auto result = table->Lookup(BuiltinType::kArrayLength, utils::Vector{arr_ptr},
                                 sem::EvaluationStage::kConstant, Source{});
     ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
@@ -263,8 +264,8 @@
     EXPECT_TRUE(result.sem->ReturnType()->Is<type::U32>());
     ASSERT_EQ(result.sem->Parameters().Length(), 1u);
     auto* param_type = result.sem->Parameters()[0]->Type();
-    ASSERT_TRUE(param_type->Is<sem::Pointer>());
-    EXPECT_TRUE(param_type->As<sem::Pointer>()->StoreType()->Is<sem::Array>());
+    ASSERT_TRUE(param_type->Is<type::Pointer>());
+    EXPECT_TRUE(param_type->As<type::Pointer>()->StoreType()->Is<sem::Array>());
 }
 
 TEST_F(IntrinsicTableTest, MismatchArray) {
@@ -446,7 +447,7 @@
     auto result = table->Lookup(
         BuiltinType::kCos,
         utils::Vector{
-            create<sem::Reference>(f32, ast::AddressSpace::kFunction, ast::Access::kReadWrite),
+            create<type::Reference>(f32, ast::AddressSpace::kFunction, ast::Access::kReadWrite),
         },
         sem::EvaluationStage::kConstant, Source{});
     ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
@@ -546,8 +547,8 @@
 
 TEST_F(IntrinsicTableTest, MatchDifferentArgsElementType_Builtin_RuntimeEval) {
     auto* af = create<type::AbstractFloat>();
-    auto* bool_ref = create<sem::Reference>(create<type::Bool>(), ast::AddressSpace::kFunction,
-                                            ast::Access::kReadWrite);
+    auto* bool_ref = create<type::Reference>(create<type::Bool>(), ast::AddressSpace::kFunction,
+                                             ast::Access::kReadWrite);
     auto result = table->Lookup(BuiltinType::kSelect, utils::Vector{af, af, bool_ref},
                                 sem::EvaluationStage::kRuntime, Source{});
     ASSERT_NE(result.sem, nullptr) << Diagnostics().str();
diff --git a/src/tint/resolver/is_host_shareable_test.cc b/src/tint/resolver/is_host_shareable_test.cc
index 51bc52b..e2fb104 100644
--- a/src/tint/resolver/is_host_shareable_test.cc
+++ b/src/tint/resolver/is_host_shareable_test.cc
@@ -95,8 +95,8 @@
 }
 
 TEST_F(ResolverIsHostShareable, Pointer) {
-    auto* ptr = create<sem::Pointer>(create<type::I32>(), ast::AddressSpace::kPrivate,
-                                     ast::Access::kReadWrite);
+    auto* ptr = create<type::Pointer>(create<type::I32>(), ast::AddressSpace::kPrivate,
+                                      ast::Access::kReadWrite);
     EXPECT_FALSE(r()->IsHostShareable(ptr));
 }
 
diff --git a/src/tint/resolver/is_storeable_test.cc b/src/tint/resolver/is_storeable_test.cc
index 4f7edc4..73368b4 100644
--- a/src/tint/resolver/is_storeable_test.cc
+++ b/src/tint/resolver/is_storeable_test.cc
@@ -78,8 +78,8 @@
 }
 
 TEST_F(ResolverIsStorableTest, Pointer) {
-    auto* ptr = create<sem::Pointer>(create<type::I32>(), ast::AddressSpace::kPrivate,
-                                     ast::Access::kReadWrite);
+    auto* ptr = create<type::Pointer>(create<type::I32>(), ast::AddressSpace::kPrivate,
+                                      ast::Access::kReadWrite);
     EXPECT_FALSE(r()->IsStorable(ptr));
 }
 
diff --git a/src/tint/resolver/ptr_ref_test.cc b/src/tint/resolver/ptr_ref_test.cc
index 872bcdc..ecaafa7 100644
--- a/src/tint/resolver/ptr_ref_test.cc
+++ b/src/tint/resolver/ptr_ref_test.cc
@@ -14,7 +14,7 @@
 
 #include "src/tint/resolver/resolver.h"
 #include "src/tint/resolver/resolver_test_helper.h"
-#include "src/tint/sem/reference.h"
+#include "src/tint/type/reference.h"
 
 #include "gmock/gmock.h"
 
@@ -36,9 +36,9 @@
 
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
-    ASSERT_TRUE(TypeOf(expr)->Is<sem::Pointer>());
-    EXPECT_TRUE(TypeOf(expr)->As<sem::Pointer>()->StoreType()->Is<type::I32>());
-    EXPECT_EQ(TypeOf(expr)->As<sem::Pointer>()->AddressSpace(), ast::AddressSpace::kFunction);
+    ASSERT_TRUE(TypeOf(expr)->Is<type::Pointer>());
+    EXPECT_TRUE(TypeOf(expr)->As<type::Pointer>()->StoreType()->Is<type::I32>());
+    EXPECT_EQ(TypeOf(expr)->As<type::Pointer>()->AddressSpace(), ast::AddressSpace::kFunction);
 }
 
 TEST_F(ResolverPtrRefTest, AddressOfThenDeref) {
@@ -52,8 +52,8 @@
 
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
-    ASSERT_TRUE(TypeOf(expr)->Is<sem::Reference>());
-    EXPECT_TRUE(TypeOf(expr)->As<sem::Reference>()->StoreType()->Is<type::I32>());
+    ASSERT_TRUE(TypeOf(expr)->Is<type::Reference>());
+    EXPECT_TRUE(TypeOf(expr)->As<type::Reference>()->StoreType()->Is<type::I32>());
 }
 
 TEST_F(ResolverPtrRefTest, DefaultPtrAddressSpace) {
@@ -83,22 +83,22 @@
 
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
-    ASSERT_TRUE(TypeOf(function_ptr)->Is<sem::Pointer>())
+    ASSERT_TRUE(TypeOf(function_ptr)->Is<type::Pointer>())
         << "function_ptr is " << TypeOf(function_ptr)->TypeInfo().name;
-    ASSERT_TRUE(TypeOf(private_ptr)->Is<sem::Pointer>())
+    ASSERT_TRUE(TypeOf(private_ptr)->Is<type::Pointer>())
         << "private_ptr is " << TypeOf(private_ptr)->TypeInfo().name;
-    ASSERT_TRUE(TypeOf(workgroup_ptr)->Is<sem::Pointer>())
+    ASSERT_TRUE(TypeOf(workgroup_ptr)->Is<type::Pointer>())
         << "workgroup_ptr is " << TypeOf(workgroup_ptr)->TypeInfo().name;
-    ASSERT_TRUE(TypeOf(uniform_ptr)->Is<sem::Pointer>())
+    ASSERT_TRUE(TypeOf(uniform_ptr)->Is<type::Pointer>())
         << "uniform_ptr is " << TypeOf(uniform_ptr)->TypeInfo().name;
-    ASSERT_TRUE(TypeOf(storage_ptr)->Is<sem::Pointer>())
+    ASSERT_TRUE(TypeOf(storage_ptr)->Is<type::Pointer>())
         << "storage_ptr is " << TypeOf(storage_ptr)->TypeInfo().name;
 
-    EXPECT_EQ(TypeOf(function_ptr)->As<sem::Pointer>()->Access(), ast::Access::kReadWrite);
-    EXPECT_EQ(TypeOf(private_ptr)->As<sem::Pointer>()->Access(), ast::Access::kReadWrite);
-    EXPECT_EQ(TypeOf(workgroup_ptr)->As<sem::Pointer>()->Access(), ast::Access::kReadWrite);
-    EXPECT_EQ(TypeOf(uniform_ptr)->As<sem::Pointer>()->Access(), ast::Access::kRead);
-    EXPECT_EQ(TypeOf(storage_ptr)->As<sem::Pointer>()->Access(), ast::Access::kRead);
+    EXPECT_EQ(TypeOf(function_ptr)->As<type::Pointer>()->Access(), ast::Access::kReadWrite);
+    EXPECT_EQ(TypeOf(private_ptr)->As<type::Pointer>()->Access(), ast::Access::kReadWrite);
+    EXPECT_EQ(TypeOf(workgroup_ptr)->As<type::Pointer>()->Access(), ast::Access::kReadWrite);
+    EXPECT_EQ(TypeOf(uniform_ptr)->As<type::Pointer>()->Access(), ast::Access::kRead);
+    EXPECT_EQ(TypeOf(storage_ptr)->As<type::Pointer>()->Access(), ast::Access::kRead);
 }
 
 }  // namespace
diff --git a/src/tint/resolver/ptr_ref_validation_test.cc b/src/tint/resolver/ptr_ref_validation_test.cc
index 176a836..efd77a6 100644
--- a/src/tint/resolver/ptr_ref_validation_test.cc
+++ b/src/tint/resolver/ptr_ref_validation_test.cc
@@ -15,7 +15,7 @@
 #include "src/tint/ast/bitcast_expression.h"
 #include "src/tint/resolver/resolver.h"
 #include "src/tint/resolver/resolver_test_helper.h"
-#include "src/tint/sem/reference.h"
+#include "src/tint/type/reference.h"
 
 #include "gmock/gmock.h"
 
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index bf12325..31e7abf 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -65,8 +65,6 @@
 #include "src/tint/sem/materialize.h"
 #include "src/tint/sem/member_accessor_expression.h"
 #include "src/tint/sem/module.h"
-#include "src/tint/sem/pointer.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/sem/statement.h"
 #include "src/tint/sem/struct.h"
 #include "src/tint/sem/switch_statement.h"
@@ -79,6 +77,8 @@
 #include "src/tint/type/depth_multisampled_texture.h"
 #include "src/tint/type/depth_texture.h"
 #include "src/tint/type/multisampled_texture.h"
+#include "src/tint/type/pointer.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/type/sampled_texture.h"
 #include "src/tint/type/sampler.h"
 #include "src/tint/type/storage_texture.h"
@@ -257,13 +257,13 @@
             }
             return nullptr;
         },
-        [&](const ast::Pointer* t) -> sem::Pointer* {
+        [&](const ast::Pointer* t) -> type::Pointer* {
             if (auto* el = Type(t->type)) {
                 auto access = t->access;
                 if (access == ast::Access::kUndefined) {
                     access = DefaultAccessForAddressSpace(t->address_space);
                 }
-                auto ptr = builder_->create<sem::Pointer>(el, t->address_space, access);
+                auto ptr = builder_->create<type::Pointer>(el, t->address_space, access);
                 if (!ptr) {
                     return nullptr;
                 }
@@ -638,7 +638,7 @@
         return nullptr;
     }
 
-    auto* var_ty = builder_->create<sem::Reference>(storage_ty, address_space, access);
+    auto* var_ty = builder_->create<type::Reference>(storage_ty, address_space, access);
 
     if (!ApplyAddressSpaceUsageToType(address_space, var_ty,
                                       var->type ? var->type->source : var->source)) {
@@ -748,7 +748,7 @@
         return nullptr;
     }
 
-    if (auto* ptr = ty->As<sem::Pointer>()) {
+    if (auto* ptr = ty->As<type::Pointer>()) {
         // For MSL, we push module-scope variables into the entry point as pointer
         // parameters, so we also need to handle their store type.
         if (!ApplyAddressSpaceUsageToType(
@@ -1578,7 +1578,7 @@
     if (!expr) {
         return;
     }
-    if (!expr->Type()->Is<sem::Reference>()) {
+    if (!expr->Type()->Is<type::Reference>()) {
         return;
     }
     if (!current_function_) {
@@ -1649,7 +1649,7 @@
     std::unordered_map<const sem::Variable*, const sem::Expression*> arg_writes;
     for (size_t i = 0; i < args.Length(); i++) {
         auto* arg = args[i];
-        if (!arg->Type()->Is<sem::Pointer>()) {
+        if (!arg->Type()->Is<type::Pointer>()) {
             continue;
         }
 
@@ -1890,8 +1890,8 @@
     }
 
     // If we're extracting from a reference, we return a reference.
-    if (auto* ref = obj_raw_ty->As<sem::Reference>()) {
-        ty = builder_->create<sem::Reference>(ty, ref->AddressSpace(), ref->Access());
+    if (auto* ref = obj_raw_ty->As<type::Reference>()) {
+        ty = builder_->create<type::Reference>(ty, ref->AddressSpace(), ref->Access());
     }
 
     auto stage = sem::EarliestStage(obj->Stage(), idx->Stage());
@@ -2664,8 +2664,8 @@
             ty = member->Type();
 
             // If we're extracting from a reference, we return a reference.
-            if (auto* ref = structure->As<sem::Reference>()) {
-                ty = builder_->create<sem::Reference>(ty, ref->AddressSpace(), ref->Access());
+            if (auto* ref = structure->As<type::Reference>()) {
+                ty = builder_->create<type::Reference>(ty, ref->AddressSpace(), ref->Access());
             }
 
             auto val = const_eval_.MemberAccess(object, member);
@@ -2733,8 +2733,8 @@
                 // A single element swizzle is just the type of the vector.
                 ty = vec->type();
                 // If we're extracting from a reference, we return a reference.
-                if (auto* ref = structure->As<sem::Reference>()) {
-                    ty = builder_->create<sem::Reference>(ty, ref->AddressSpace(), ref->Access());
+                if (auto* ref = structure->As<type::Reference>()) {
+                    ty = builder_->create<type::Reference>(ty, ref->AddressSpace(), ref->Access());
                 }
             } else {
                 // The vector will have a number of components equal to the length of
@@ -2828,7 +2828,7 @@
 
     switch (unary->op) {
         case ast::UnaryOp::kAddressOf:
-            if (auto* ref = expr_ty->As<sem::Reference>()) {
+            if (auto* ref = expr_ty->As<type::Reference>()) {
                 if (ref->StoreType()->UnwrapRef()->is_handle()) {
                     AddError("cannot take the address of expression in handle address space",
                              unary->expr->source);
@@ -2843,8 +2843,8 @@
                     return nullptr;
                 }
 
-                ty = builder_->create<sem::Pointer>(ref->StoreType(), ref->AddressSpace(),
-                                                    ref->Access());
+                ty = builder_->create<type::Pointer>(ref->StoreType(), ref->AddressSpace(),
+                                                     ref->Access());
 
                 root_ident = expr->RootIdentifier();
             } else {
@@ -2854,9 +2854,9 @@
             break;
 
         case ast::UnaryOp::kIndirection:
-            if (auto* ptr = expr_ty->As<sem::Pointer>()) {
-                ty = builder_->create<sem::Reference>(ptr->StoreType(), ptr->AddressSpace(),
-                                                      ptr->Access());
+            if (auto* ptr = expr_ty->As<type::Pointer>()) {
+                ty = builder_->create<type::Reference>(ptr->StoreType(), ptr->AddressSpace(),
+                                                       ptr->Access());
                 root_ident = expr->RootIdentifier();
             } else {
                 AddError("cannot dereference expression of type '" + sem_.TypeNameOf(expr_ty) + "'",
diff --git a/src/tint/resolver/resolver_test.cc b/src/tint/resolver/resolver_test.cc
index 7f3ea6a..b64290a 100644
--- a/src/tint/resolver/resolver_test.cc
+++ b/src/tint/resolver/resolver_test.cc
@@ -39,10 +39,10 @@
 #include "src/tint/sem/function.h"
 #include "src/tint/sem/member_accessor_expression.h"
 #include "src/tint/sem/module.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/sem/statement.h"
 #include "src/tint/sem/switch_statement.h"
 #include "src/tint/sem/variable.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/type/sampled_texture.h"
 
 using ::testing::ElementsAre;
@@ -437,7 +437,7 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(a), nullptr);
-    auto* ref = TypeOf(a)->As<sem::Reference>();
+    auto* ref = TypeOf(a)->As<type::Reference>();
     ASSERT_NE(ref, nullptr);
     auto* ary = ref->StoreType()->As<sem::Array>();
     EXPECT_EQ(ary->Count(), create<type::ConstantArrayCount>(10u));
@@ -450,7 +450,7 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(a), nullptr);
-    auto* ref = TypeOf(a)->As<sem::Reference>();
+    auto* ref = TypeOf(a)->As<type::Reference>();
     ASSERT_NE(ref, nullptr);
     auto* ary = ref->StoreType()->As<sem::Array>();
     EXPECT_EQ(ary->Count(), create<type::ConstantArrayCount>(10u));
@@ -465,7 +465,7 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(a), nullptr);
-    auto* ref = TypeOf(a)->As<sem::Reference>();
+    auto* ref = TypeOf(a)->As<type::Reference>();
     ASSERT_NE(ref, nullptr);
     auto* ary = ref->StoreType()->As<sem::Array>();
     EXPECT_EQ(ary->Count(), create<type::ConstantArrayCount>(10u));
@@ -480,7 +480,7 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(a), nullptr);
-    auto* ref = TypeOf(a)->As<sem::Reference>();
+    auto* ref = TypeOf(a)->As<type::Reference>();
     ASSERT_NE(ref, nullptr);
     auto* ary = ref->StoreType()->As<sem::Array>();
     EXPECT_EQ(ary->Count(), create<type::ConstantArrayCount>(10u));
@@ -495,7 +495,7 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(a), nullptr);
-    auto* ref = TypeOf(a)->As<sem::Reference>();
+    auto* ref = TypeOf(a)->As<type::Reference>();
     ASSERT_NE(ref, nullptr);
     auto* ary = ref->StoreType()->As<sem::Array>();
     auto* sem_override = Sem().Get<sem::GlobalVariable>(override);
@@ -514,12 +514,12 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(a), nullptr);
-    auto* ref_a = TypeOf(a)->As<sem::Reference>();
+    auto* ref_a = TypeOf(a)->As<type::Reference>();
     ASSERT_NE(ref_a, nullptr);
     auto* ary_a = ref_a->StoreType()->As<sem::Array>();
 
     ASSERT_NE(TypeOf(b), nullptr);
-    auto* ref_b = TypeOf(b)->As<sem::Reference>();
+    auto* ref_b = TypeOf(b)->As<type::Reference>();
     ASSERT_NE(ref_b, nullptr);
     auto* ary_b = ref_b->StoreType()->As<sem::Array>();
 
@@ -540,7 +540,7 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(a), nullptr);
-    auto* ref = TypeOf(a)->As<sem::Reference>();
+    auto* ref = TypeOf(a)->As<type::Reference>();
     ASSERT_NE(ref, nullptr);
     auto* ary = ref->StoreType()->As<sem::Array>();
     auto* sem_override = Sem().Get<sem::GlobalVariable>(override);
@@ -561,12 +561,12 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(a), nullptr);
-    auto* ref_a = TypeOf(a)->As<sem::Reference>();
+    auto* ref_a = TypeOf(a)->As<type::Reference>();
     ASSERT_NE(ref_a, nullptr);
     auto* ary_a = ref_a->StoreType()->As<sem::Array>();
 
     ASSERT_NE(TypeOf(b), nullptr);
-    auto* ref_b = TypeOf(b)->As<sem::Reference>();
+    auto* ref_b = TypeOf(b)->As<type::Reference>();
     ASSERT_NE(ref_b, nullptr);
     auto* ary_b = ref_b->StoreType()->As<sem::Array>();
 
@@ -707,7 +707,7 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(ident), nullptr);
-    ASSERT_TRUE(TypeOf(ident)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(ident)->Is<type::Reference>());
     EXPECT_TRUE(TypeOf(ident)->UnwrapRef()->Is<type::F32>());
     EXPECT_TRUE(CheckVarUsers(my_var, utils::Vector{ident}));
     ASSERT_NE(VarOf(ident), nullptr);
@@ -784,11 +784,11 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(my_var_a), nullptr);
-    ASSERT_TRUE(TypeOf(my_var_a)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(my_var_a)->Is<type::Reference>());
     EXPECT_TRUE(TypeOf(my_var_a)->UnwrapRef()->Is<type::F32>());
     EXPECT_EQ(StmtOf(my_var_a), assign);
     ASSERT_NE(TypeOf(my_var_b), nullptr);
-    ASSERT_TRUE(TypeOf(my_var_b)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(my_var_b)->Is<type::Reference>());
     EXPECT_TRUE(TypeOf(my_var_b)->UnwrapRef()->Is<type::F32>());
     EXPECT_EQ(StmtOf(my_var_b), assign);
     EXPECT_TRUE(CheckVarUsers(var, utils::Vector{my_var_a, my_var_b}));
@@ -814,11 +814,11 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(v), nullptr);
-    ASSERT_TRUE(TypeOf(v)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(v)->Is<type::Reference>());
     EXPECT_TRUE(TypeOf(v)->UnwrapRef()->Is<type::F32>());
     EXPECT_EQ(StmtOf(v), p_decl);
     ASSERT_NE(TypeOf(p), nullptr);
-    ASSERT_TRUE(TypeOf(p)->Is<sem::Pointer>());
+    ASSERT_TRUE(TypeOf(p)->Is<type::Pointer>());
     EXPECT_TRUE(TypeOf(p)->UnwrapPtr()->Is<type::F32>());
     EXPECT_EQ(StmtOf(p), assign);
 }
@@ -1250,9 +1250,9 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(mem), nullptr);
-    ASSERT_TRUE(TypeOf(mem)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(mem)->Is<type::Reference>());
 
-    auto* ref = TypeOf(mem)->As<sem::Reference>();
+    auto* ref = TypeOf(mem)->As<type::Reference>();
     EXPECT_TRUE(ref->StoreType()->Is<type::F32>());
     auto* sma = Sem().Get(mem)->As<sem::StructMemberAccess>();
     ASSERT_NE(sma, nullptr);
@@ -1274,9 +1274,9 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(mem), nullptr);
-    ASSERT_TRUE(TypeOf(mem)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(mem)->Is<type::Reference>());
 
-    auto* ref = TypeOf(mem)->As<sem::Reference>();
+    auto* ref = TypeOf(mem)->As<type::Reference>();
     EXPECT_TRUE(ref->StoreType()->Is<type::F32>());
     auto* sma = Sem().Get(mem)->As<sem::StructMemberAccess>();
     ASSERT_NE(sma, nullptr);
@@ -1312,9 +1312,9 @@
     EXPECT_TRUE(r()->Resolve()) << r()->error();
 
     ASSERT_NE(TypeOf(mem), nullptr);
-    ASSERT_TRUE(TypeOf(mem)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(mem)->Is<type::Reference>());
 
-    auto* ref = TypeOf(mem)->As<sem::Reference>();
+    auto* ref = TypeOf(mem)->As<type::Reference>();
     ASSERT_TRUE(ref->StoreType()->Is<type::F32>());
     auto* sma = Sem().Get(mem)->As<sem::Swizzle>();
     ASSERT_NE(sma, nullptr);
diff --git a/src/tint/resolver/resolver_test_helper.h b/src/tint/resolver/resolver_test_helper.h
index e4625b6..83e1a5b 100644
--- a/src/tint/resolver/resolver_test_helper.h
+++ b/src/tint/resolver/resolver_test_helper.h
@@ -616,8 +616,8 @@
     /// @param b the ProgramBuilder
     /// @return the semantic aliased type
     static inline const type::Type* Sem(ProgramBuilder& b) {
-        return b.create<sem::Pointer>(DataType<T>::Sem(b), ast::AddressSpace::kPrivate,
-                                      ast::Access::kReadWrite);
+        return b.create<type::Pointer>(DataType<T>::Sem(b), ast::AddressSpace::kPrivate,
+                                       ast::Access::kReadWrite);
     }
 
     /// @param b the ProgramBuilder
diff --git a/src/tint/resolver/type_initializer_validation_test.cc b/src/tint/resolver/type_initializer_validation_test.cc
index cbb6b89..053fba1 100644
--- a/src/tint/resolver/type_initializer_validation_test.cc
+++ b/src/tint/resolver/type_initializer_validation_test.cc
@@ -14,9 +14,9 @@
 
 #include "gmock/gmock.h"
 #include "src/tint/resolver/resolver_test_helper.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/sem/type_conversion.h"
 #include "src/tint/sem/type_initializer.h"
+#include "src/tint/type/reference.h"
 
 using namespace tint::number_suffixes;  // NOLINT
 
@@ -67,12 +67,12 @@
     WrapInFunction(a, b, Assign(a_ident, "a"), Assign(b_ident, "b"));
 
     ASSERT_TRUE(r()->Resolve()) << r()->error();
-    ASSERT_TRUE(TypeOf(a_ident)->Is<sem::Reference>());
-    EXPECT_TRUE(TypeOf(a_ident)->As<sem::Reference>()->StoreType()->Is<type::I32>());
-    EXPECT_EQ(TypeOf(a_ident)->As<sem::Reference>()->AddressSpace(), ast::AddressSpace::kFunction);
-    ASSERT_TRUE(TypeOf(b_ident)->Is<sem::Reference>());
-    EXPECT_TRUE(TypeOf(b_ident)->As<sem::Reference>()->StoreType()->Is<type::I32>());
-    EXPECT_EQ(TypeOf(b_ident)->As<sem::Reference>()->AddressSpace(), ast::AddressSpace::kFunction);
+    ASSERT_TRUE(TypeOf(a_ident)->Is<type::Reference>());
+    EXPECT_TRUE(TypeOf(a_ident)->As<type::Reference>()->StoreType()->Is<type::I32>());
+    EXPECT_EQ(TypeOf(a_ident)->As<type::Reference>()->AddressSpace(), ast::AddressSpace::kFunction);
+    ASSERT_TRUE(TypeOf(b_ident)->Is<type::Reference>());
+    EXPECT_TRUE(TypeOf(b_ident)->As<type::Reference>()->StoreType()->Is<type::I32>());
+    EXPECT_EQ(TypeOf(b_ident)->As<type::Reference>()->AddressSpace(), ast::AddressSpace::kFunction);
 }
 
 using InferTypeTest_FromInitializerExpression = ResolverTestWithParam<Params>;
@@ -95,8 +95,8 @@
 
     ASSERT_TRUE(r()->Resolve()) << r()->error();
     auto* got = TypeOf(a_ident);
-    auto* expected = create<sem::Reference>(params.create_rhs_sem_type(*this),
-                                            ast::AddressSpace::kFunction, ast::Access::kReadWrite);
+    auto* expected = create<type::Reference>(params.create_rhs_sem_type(*this),
+                                             ast::AddressSpace::kFunction, ast::Access::kReadWrite);
     ASSERT_EQ(got, expected) << "got:      " << FriendlyName(got) << "\n"
                              << "expected: " << FriendlyName(expected) << "\n";
 }
@@ -149,8 +149,8 @@
 
     ASSERT_TRUE(r()->Resolve()) << r()->error();
     auto* got = TypeOf(a_ident);
-    auto* expected = create<sem::Reference>(params.create_rhs_sem_type(*this),
-                                            ast::AddressSpace::kFunction, ast::Access::kReadWrite);
+    auto* expected = create<type::Reference>(params.create_rhs_sem_type(*this),
+                                             ast::AddressSpace::kFunction, ast::Access::kReadWrite);
     ASSERT_EQ(got, expected) << "got:      " << FriendlyName(got) << "\n"
                              << "expected: " << FriendlyName(expected) << "\n";
 }
@@ -197,8 +197,8 @@
 
     ASSERT_TRUE(r()->Resolve()) << r()->error();
     auto* got = TypeOf(a_ident);
-    auto* expected = create<sem::Reference>(params.create_rhs_sem_type(*this),
-                                            ast::AddressSpace::kFunction, ast::Access::kReadWrite);
+    auto* expected = create<type::Reference>(params.create_rhs_sem_type(*this),
+                                             ast::AddressSpace::kFunction, ast::Access::kReadWrite);
     ASSERT_EQ(got, expected) << "got:      " << FriendlyName(got) << "\n"
                              << "expected: " << FriendlyName(expected) << "\n";
 }
diff --git a/src/tint/resolver/uniformity.cc b/src/tint/resolver/uniformity.cc
index b47be22..db1578f 100644
--- a/src/tint/resolver/uniformity.cc
+++ b/src/tint/resolver/uniformity.cc
@@ -172,7 +172,7 @@
             parameters[i].sem = sem;
 
             Node* node_init;
-            if (sem->Type()->Is<sem::Pointer>()) {
+            if (sem->Type()->Is<type::Pointer>()) {
                 node_init = CreateNode("ptrparam_" + name + "_init");
                 parameters[i].pointer_return_value = CreateNode("ptrparam_" + name + "_return");
                 local_var_decls.Add(sem);
@@ -982,7 +982,7 @@
                     node = v;
 
                     // Store if lhs is a partial pointer
-                    if (sem_var->Type()->Is<sem::Pointer>()) {
+                    if (sem_var->Type()->Is<type::Pointer>()) {
                         auto* init = sem_.Get(decl->variable->initializer);
                         if (auto* unary_init = init->Declaration()->As<ast::UnaryOpExpression>()) {
                             auto* e = UnwrapIndirectAndAddressOfChain(unary_init);
@@ -1378,7 +1378,7 @@
                 }
 
                 auto* sem_arg = sem_.Get(call->args[i]);
-                if (sem_arg->Type()->Is<sem::Pointer>()) {
+                if (sem_arg->Type()->Is<type::Pointer>()) {
                     auto* ptr_result =
                         CreateNode(name + "_ptrarg_" + std::to_string(i) + "_result", call);
                     ptr_result->type = Node::kFunctionCallPointerArgumentResult;
diff --git a/src/tint/resolver/validator.cc b/src/tint/resolver/validator.cc
index 18cb152..ec4f4f6 100644
--- a/src/tint/resolver/validator.cc
+++ b/src/tint/resolver/validator.cc
@@ -57,8 +57,6 @@
 #include "src/tint/sem/loop_statement.h"
 #include "src/tint/sem/materialize.h"
 #include "src/tint/sem/member_accessor_expression.h"
-#include "src/tint/sem/pointer.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/sem/statement.h"
 #include "src/tint/sem/struct.h"
 #include "src/tint/sem/switch_statement.h"
@@ -70,6 +68,8 @@
 #include "src/tint/type/depth_multisampled_texture.h"
 #include "src/tint/type/depth_texture.h"
 #include "src/tint/type/multisampled_texture.h"
+#include "src/tint/type/pointer.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/type/sampled_texture.h"
 #include "src/tint/type/sampler.h"
 #include "src/tint/type/storage_texture.h"
@@ -270,7 +270,7 @@
     return true;
 }
 
-bool Validator::Pointer(const ast::Pointer* a, const sem::Pointer* s) const {
+bool Validator::Pointer(const ast::Pointer* a, const type::Pointer* s) const {
     if (s->AddressSpace() == ast::AddressSpace::kUndefined) {
         AddError("ptr missing address space", a->source);
         return false;
@@ -721,7 +721,7 @@
     auto* decl = v->Declaration();
     auto* storage_ty = v->Type()->UnwrapRef();
 
-    if (!(storage_ty->IsConstructible() || storage_ty->Is<sem::Pointer>())) {
+    if (!(storage_ty->IsConstructible() || storage_ty->Is<type::Pointer>())) {
         AddError(sem_.TypeNameOf(storage_ty) + " cannot be used as the type of a 'let'",
                  decl->source);
         return false;
@@ -798,7 +798,7 @@
         }
     }
 
-    if (auto* ref = var->Type()->As<sem::Pointer>()) {
+    if (auto* ref = var->Type()->As<type::Pointer>()) {
         if (IsValidationEnabled(decl->attributes, ast::DisabledValidation::kIgnoreAddressSpace)) {
             bool ok = false;
 
@@ -832,7 +832,7 @@
             AddError("type of function parameter must be constructible", decl->type->source);
             return false;
         }
-    } else if (!var->Type()->IsAnyOf<type::Texture, type::Sampler, sem::Pointer>()) {
+    } else if (!var->Type()->IsAnyOf<type::Texture, type::Sampler, type::Pointer>()) {
         AddError("type of function parameter cannot be " + sem_.TypeNameOf(var->Type()),
                  decl->source);
         return false;
@@ -1662,17 +1662,17 @@
             return false;
         }
 
-        if (param_type->Is<sem::Pointer>() &&
+        if (param_type->Is<type::Pointer>() &&
             !enabled_extensions_.Contains(ast::Extension::kChromiumExperimentalFullPtrParameters)) {
             // https://gpuweb.github.io/gpuweb/wgsl/#function-restriction
             // Each argument of pointer type to a user-defined function must have the same memory
             // view as its root identifier.
             // We can validate this by just comparing the store type of the argument with that of
             // its root identifier, as these will match iff the memory view is the same.
-            auto* arg_store_type = arg_type->As<sem::Pointer>()->StoreType();
+            auto* arg_store_type = arg_type->As<type::Pointer>()->StoreType();
             auto* root = call->Arguments()[i]->RootIdentifier();
-            auto* root_ptr_ty = root->Type()->As<sem::Pointer>();
-            auto* root_ref_ty = root->Type()->As<sem::Reference>();
+            auto* root_ptr_ty = root->Type()->As<type::Pointer>();
+            auto* root_ref_ty = root->Type()->As<type::Reference>();
             TINT_ASSERT(Resolver, root_ptr_ty || root_ref_ty);
             const type::Type* root_store_type;
             if (root_ptr_ty) {
@@ -2266,7 +2266,7 @@
         // https://www.w3.org/TR/WGSL/#phony-assignment-section
         auto* ty = rhs_ty->UnwrapRef();
         if (!ty->IsConstructible() &&
-            !ty->IsAnyOf<sem::Pointer, type::Texture, type::Sampler, type::AbstractNumeric>()) {
+            !ty->IsAnyOf<type::Pointer, type::Texture, type::Sampler, type::AbstractNumeric>()) {
             AddError("cannot assign '" + sem_.TypeNameOf(rhs_ty) +
                          "' to '_'. '_' can only be assigned a constructible, pointer, texture or "
                          "sampler type",
@@ -2293,7 +2293,7 @@
         }
     }
 
-    auto* lhs_ref = lhs_ty->As<sem::Reference>();
+    auto* lhs_ref = lhs_ty->As<type::Reference>();
     if (!lhs_ref) {
         // LHS is not a reference, so it has no storage.
         AddError("cannot assign to value of type '" + sem_.TypeNameOf(lhs_ty) + "'", lhs->source);
@@ -2342,7 +2342,7 @@
     }
 
     auto const* lhs_ty = sem_.TypeOf(lhs);
-    auto* lhs_ref = lhs_ty->As<sem::Reference>();
+    auto* lhs_ref = lhs_ty->As<type::Reference>();
     if (!lhs_ref) {
         // LHS is not a reference, so it has no storage.
         AddError("cannot modify value of type '" + sem_.TypeNameOf(lhs_ty) + "'", lhs->source);
diff --git a/src/tint/resolver/validator.h b/src/tint/resolver/validator.h
index d666555..14b1ab2 100644
--- a/src/tint/resolver/validator.h
+++ b/src/tint/resolver/validator.h
@@ -173,7 +173,7 @@
     /// @param a the pointer ast node
     /// @param s the pointer sem node
     /// @returns true on success, false otherwise.
-    bool Pointer(const ast::Pointer* a, const sem::Pointer* s) const;
+    bool Pointer(const ast::Pointer* a, const type::Pointer* s) const;
 
     /// Validates an assignment
     /// @param a the assignment statement
diff --git a/src/tint/resolver/validator_is_storeable_test.cc b/src/tint/resolver/validator_is_storeable_test.cc
index 6e464bc..7e4a5ba 100644
--- a/src/tint/resolver/validator_is_storeable_test.cc
+++ b/src/tint/resolver/validator_is_storeable_test.cc
@@ -78,8 +78,8 @@
 }
 
 TEST_F(ValidatorIsStorableTest, Pointer) {
-    auto* ptr = create<sem::Pointer>(create<type::I32>(), ast::AddressSpace::kPrivate,
-                                     ast::Access::kReadWrite);
+    auto* ptr = create<type::Pointer>(create<type::I32>(), ast::AddressSpace::kPrivate,
+                                      ast::Access::kReadWrite);
     EXPECT_FALSE(v()->IsStorable(ptr));
 }
 
diff --git a/src/tint/resolver/variable_test.cc b/src/tint/resolver/variable_test.cc
index a0a5ae7..16491c0 100644
--- a/src/tint/resolver/variable_test.cc
+++ b/src/tint/resolver/variable_test.cc
@@ -14,7 +14,7 @@
 
 #include "src/tint/resolver/resolver.h"
 #include "src/tint/resolver/resolver_test_helper.h"
-#include "src/tint/sem/reference.h"
+#include "src/tint/type/reference.h"
 
 #include "gmock/gmock.h"
 
@@ -68,21 +68,21 @@
     ASSERT_TRUE(r()->Resolve()) << r()->error();
 
     // `var` declarations are always of reference type
-    ASSERT_TRUE(TypeOf(i)->Is<sem::Reference>());
-    ASSERT_TRUE(TypeOf(u)->Is<sem::Reference>());
-    ASSERT_TRUE(TypeOf(f)->Is<sem::Reference>());
-    ASSERT_TRUE(TypeOf(h)->Is<sem::Reference>());
-    ASSERT_TRUE(TypeOf(b)->Is<sem::Reference>());
-    ASSERT_TRUE(TypeOf(s)->Is<sem::Reference>());
-    ASSERT_TRUE(TypeOf(a)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(i)->Is<type::Reference>());
+    ASSERT_TRUE(TypeOf(u)->Is<type::Reference>());
+    ASSERT_TRUE(TypeOf(f)->Is<type::Reference>());
+    ASSERT_TRUE(TypeOf(h)->Is<type::Reference>());
+    ASSERT_TRUE(TypeOf(b)->Is<type::Reference>());
+    ASSERT_TRUE(TypeOf(s)->Is<type::Reference>());
+    ASSERT_TRUE(TypeOf(a)->Is<type::Reference>());
 
-    EXPECT_TRUE(TypeOf(i)->As<sem::Reference>()->StoreType()->Is<type::I32>());
-    EXPECT_TRUE(TypeOf(u)->As<sem::Reference>()->StoreType()->Is<type::U32>());
-    EXPECT_TRUE(TypeOf(f)->As<sem::Reference>()->StoreType()->Is<type::F32>());
-    EXPECT_TRUE(TypeOf(h)->As<sem::Reference>()->StoreType()->Is<type::F16>());
-    EXPECT_TRUE(TypeOf(b)->As<sem::Reference>()->StoreType()->Is<type::Bool>());
-    EXPECT_TRUE(TypeOf(s)->As<sem::Reference>()->StoreType()->Is<sem::Struct>());
-    EXPECT_TRUE(TypeOf(a)->As<sem::Reference>()->StoreType()->Is<sem::Struct>());
+    EXPECT_TRUE(TypeOf(i)->As<type::Reference>()->StoreType()->Is<type::I32>());
+    EXPECT_TRUE(TypeOf(u)->As<type::Reference>()->StoreType()->Is<type::U32>());
+    EXPECT_TRUE(TypeOf(f)->As<type::Reference>()->StoreType()->Is<type::F32>());
+    EXPECT_TRUE(TypeOf(h)->As<type::Reference>()->StoreType()->Is<type::F16>());
+    EXPECT_TRUE(TypeOf(b)->As<type::Reference>()->StoreType()->Is<type::Bool>());
+    EXPECT_TRUE(TypeOf(s)->As<type::Reference>()->StoreType()->Is<sem::Struct>());
+    EXPECT_TRUE(TypeOf(a)->As<type::Reference>()->StoreType()->Is<sem::Struct>());
 
     EXPECT_EQ(Sem().Get(i)->Initializer(), nullptr);
     EXPECT_EQ(Sem().Get(u)->Initializer(), nullptr);
@@ -141,28 +141,28 @@
     ASSERT_TRUE(r()->Resolve()) << r()->error();
 
     // `var` declarations are always of reference type
-    ASSERT_TRUE(TypeOf(i)->Is<sem::Reference>());
-    ASSERT_TRUE(TypeOf(u)->Is<sem::Reference>());
-    ASSERT_TRUE(TypeOf(f)->Is<sem::Reference>());
-    ASSERT_TRUE(TypeOf(h)->Is<sem::Reference>());
-    ASSERT_TRUE(TypeOf(b)->Is<sem::Reference>());
-    ASSERT_TRUE(TypeOf(s)->Is<sem::Reference>());
-    ASSERT_TRUE(TypeOf(a)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(i)->Is<type::Reference>());
+    ASSERT_TRUE(TypeOf(u)->Is<type::Reference>());
+    ASSERT_TRUE(TypeOf(f)->Is<type::Reference>());
+    ASSERT_TRUE(TypeOf(h)->Is<type::Reference>());
+    ASSERT_TRUE(TypeOf(b)->Is<type::Reference>());
+    ASSERT_TRUE(TypeOf(s)->Is<type::Reference>());
+    ASSERT_TRUE(TypeOf(a)->Is<type::Reference>());
 
-    EXPECT_EQ(TypeOf(i)->As<sem::Reference>()->Access(), ast::Access::kReadWrite);
-    EXPECT_EQ(TypeOf(u)->As<sem::Reference>()->Access(), ast::Access::kReadWrite);
-    EXPECT_EQ(TypeOf(f)->As<sem::Reference>()->Access(), ast::Access::kReadWrite);
-    EXPECT_EQ(TypeOf(b)->As<sem::Reference>()->Access(), ast::Access::kReadWrite);
-    EXPECT_EQ(TypeOf(s)->As<sem::Reference>()->Access(), ast::Access::kReadWrite);
-    EXPECT_EQ(TypeOf(a)->As<sem::Reference>()->Access(), ast::Access::kReadWrite);
+    EXPECT_EQ(TypeOf(i)->As<type::Reference>()->Access(), ast::Access::kReadWrite);
+    EXPECT_EQ(TypeOf(u)->As<type::Reference>()->Access(), ast::Access::kReadWrite);
+    EXPECT_EQ(TypeOf(f)->As<type::Reference>()->Access(), ast::Access::kReadWrite);
+    EXPECT_EQ(TypeOf(b)->As<type::Reference>()->Access(), ast::Access::kReadWrite);
+    EXPECT_EQ(TypeOf(s)->As<type::Reference>()->Access(), ast::Access::kReadWrite);
+    EXPECT_EQ(TypeOf(a)->As<type::Reference>()->Access(), ast::Access::kReadWrite);
 
-    EXPECT_TRUE(TypeOf(i)->As<sem::Reference>()->StoreType()->Is<type::I32>());
-    EXPECT_TRUE(TypeOf(u)->As<sem::Reference>()->StoreType()->Is<type::U32>());
-    EXPECT_TRUE(TypeOf(f)->As<sem::Reference>()->StoreType()->Is<type::F32>());
-    EXPECT_TRUE(TypeOf(h)->As<sem::Reference>()->StoreType()->Is<type::F16>());
-    EXPECT_TRUE(TypeOf(b)->As<sem::Reference>()->StoreType()->Is<type::Bool>());
-    EXPECT_TRUE(TypeOf(s)->As<sem::Reference>()->StoreType()->Is<sem::Struct>());
-    EXPECT_TRUE(TypeOf(a)->As<sem::Reference>()->StoreType()->Is<sem::Struct>());
+    EXPECT_TRUE(TypeOf(i)->As<type::Reference>()->StoreType()->Is<type::I32>());
+    EXPECT_TRUE(TypeOf(u)->As<type::Reference>()->StoreType()->Is<type::U32>());
+    EXPECT_TRUE(TypeOf(f)->As<type::Reference>()->StoreType()->Is<type::F32>());
+    EXPECT_TRUE(TypeOf(h)->As<type::Reference>()->StoreType()->Is<type::F16>());
+    EXPECT_TRUE(TypeOf(b)->As<type::Reference>()->StoreType()->Is<type::Bool>());
+    EXPECT_TRUE(TypeOf(s)->As<type::Reference>()->StoreType()->Is<sem::Struct>());
+    EXPECT_TRUE(TypeOf(a)->As<type::Reference>()->StoreType()->Is<sem::Struct>());
 
     EXPECT_EQ(Sem().Get(i)->Initializer()->Declaration(), i_c);
     EXPECT_EQ(Sem().Get(u)->Initializer()->Declaration(), u_c);
@@ -444,8 +444,8 @@
     ASSERT_TRUE(TypeOf(b)->Is<type::Bool>());
     ASSERT_TRUE(TypeOf(s)->Is<sem::Struct>());
     ASSERT_TRUE(TypeOf(a)->Is<sem::Struct>());
-    ASSERT_TRUE(TypeOf(p)->Is<sem::Pointer>());
-    ASSERT_TRUE(TypeOf(p)->As<sem::Pointer>()->StoreType()->Is<type::I32>());
+    ASSERT_TRUE(TypeOf(p)->Is<type::Pointer>());
+    ASSERT_TRUE(TypeOf(p)->As<type::Pointer>()->StoreType()->Is<type::I32>());
 
     EXPECT_EQ(Sem().Get(i)->Initializer()->Declaration(), i_c);
     EXPECT_EQ(Sem().Get(u)->Initializer()->Declaration(), u_c);
@@ -480,11 +480,11 @@
 
     ASSERT_TRUE(r()->Resolve()) << r()->error();
 
-    ASSERT_TRUE(TypeOf(expr)->Is<sem::Reference>());
-    ASSERT_TRUE(TypeOf(ptr)->Is<sem::Pointer>());
+    ASSERT_TRUE(TypeOf(expr)->Is<type::Reference>());
+    ASSERT_TRUE(TypeOf(ptr)->Is<type::Pointer>());
 
-    EXPECT_EQ(TypeOf(expr)->As<sem::Reference>()->Access(), ast::Access::kReadWrite);
-    EXPECT_EQ(TypeOf(ptr)->As<sem::Pointer>()->Access(), ast::Access::kReadWrite);
+    EXPECT_EQ(TypeOf(expr)->As<type::Reference>()->Access(), ast::Access::kReadWrite);
+    EXPECT_EQ(TypeOf(ptr)->As<type::Pointer>()->Access(), ast::Access::kReadWrite);
 }
 
 TEST_F(ResolverVariableTest, LocalLet_ShadowsAlias) {
@@ -1044,17 +1044,17 @@
 
     ASSERT_TRUE(r()->Resolve()) << r()->error();
 
-    ASSERT_TRUE(TypeOf(private_)->Is<sem::Reference>());
-    ASSERT_TRUE(TypeOf(workgroup)->Is<sem::Reference>());
-    ASSERT_TRUE(TypeOf(uniform)->Is<sem::Reference>());
-    ASSERT_TRUE(TypeOf(storage)->Is<sem::Reference>());
-    ASSERT_TRUE(TypeOf(handle)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(private_)->Is<type::Reference>());
+    ASSERT_TRUE(TypeOf(workgroup)->Is<type::Reference>());
+    ASSERT_TRUE(TypeOf(uniform)->Is<type::Reference>());
+    ASSERT_TRUE(TypeOf(storage)->Is<type::Reference>());
+    ASSERT_TRUE(TypeOf(handle)->Is<type::Reference>());
 
-    EXPECT_EQ(TypeOf(private_)->As<sem::Reference>()->Access(), ast::Access::kReadWrite);
-    EXPECT_EQ(TypeOf(workgroup)->As<sem::Reference>()->Access(), ast::Access::kReadWrite);
-    EXPECT_EQ(TypeOf(uniform)->As<sem::Reference>()->Access(), ast::Access::kRead);
-    EXPECT_EQ(TypeOf(storage)->As<sem::Reference>()->Access(), ast::Access::kRead);
-    EXPECT_EQ(TypeOf(handle)->As<sem::Reference>()->Access(), ast::Access::kRead);
+    EXPECT_EQ(TypeOf(private_)->As<type::Reference>()->Access(), ast::Access::kReadWrite);
+    EXPECT_EQ(TypeOf(workgroup)->As<type::Reference>()->Access(), ast::Access::kReadWrite);
+    EXPECT_EQ(TypeOf(uniform)->As<type::Reference>()->Access(), ast::Access::kRead);
+    EXPECT_EQ(TypeOf(storage)->As<type::Reference>()->Access(), ast::Access::kRead);
+    EXPECT_EQ(TypeOf(handle)->As<type::Reference>()->Access(), ast::Access::kRead);
 }
 
 TEST_F(ResolverVariableTest, GlobalVar_ExplicitAddressSpace) {
@@ -1066,9 +1066,9 @@
 
     ASSERT_TRUE(r()->Resolve()) << r()->error();
 
-    ASSERT_TRUE(TypeOf(storage)->Is<sem::Reference>());
+    ASSERT_TRUE(TypeOf(storage)->Is<type::Reference>());
 
-    EXPECT_EQ(TypeOf(storage)->As<sem::Reference>()->Access(), ast::Access::kReadWrite);
+    EXPECT_EQ(TypeOf(storage)->As<type::Reference>()->Access(), ast::Access::kReadWrite);
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/tint/sem/atomic.cc b/src/tint/sem/atomic.cc
index 7f62be8..7f7178e 100644
--- a/src/tint/sem/atomic.cc
+++ b/src/tint/sem/atomic.cc
@@ -15,7 +15,7 @@
 #include "src/tint/sem/atomic.h"
 
 #include "src/tint/program_builder.h"
-#include "src/tint/sem/reference.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/utils/hash.h"
 
 TINT_INSTANTIATE_TYPEINFO(tint::sem::Atomic);
@@ -28,7 +28,7 @@
           Flag::kFixedFootprint,
       }),
       subtype_(subtype) {
-    TINT_ASSERT(AST, !subtype->Is<Reference>());
+    TINT_ASSERT(AST, !subtype->Is<type::Reference>());
 }
 
 size_t Atomic::Hash() const {
diff --git a/src/tint/sem/variable.cc b/src/tint/sem/variable.cc
index 4de2cdd..0dc279e 100644
--- a/src/tint/sem/variable.cc
+++ b/src/tint/sem/variable.cc
@@ -19,7 +19,7 @@
 #include "src/tint/ast/identifier_expression.h"
 #include "src/tint/ast/parameter.h"
 #include "src/tint/ast/variable.h"
-#include "src/tint/sem/pointer.h"
+#include "src/tint/type/pointer.h"
 
 TINT_INSTANTIATE_TYPEINFO(tint::sem::Variable);
 TINT_INSTANTIATE_TYPEINFO(tint::sem::GlobalVariable);
@@ -96,7 +96,7 @@
            /* has_side_effects */ false),
       variable_(variable) {
     auto* type = variable->Type();
-    if (type->Is<sem::Pointer>() && variable->Initializer()) {
+    if (type->Is<type::Pointer>() && variable->Initializer()) {
         root_identifier_ = variable->Initializer()->RootIdentifier();
     } else {
         root_identifier_ = variable;
diff --git a/src/tint/transform/calculate_array_length.cc b/src/tint/transform/calculate_array_length.cc
index a87e11d..25cec21 100644
--- a/src/tint/transform/calculate_array_length.cc
+++ b/src/tint/transform/calculate_array_length.cc
@@ -23,11 +23,11 @@
 #include "src/tint/sem/block_statement.h"
 #include "src/tint/sem/call.h"
 #include "src/tint/sem/function.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/sem/statement.h"
 #include "src/tint/sem/struct.h"
 #include "src/tint/sem/variable.h"
 #include "src/tint/transform/simplify_pointers.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/utils/hash.h"
 #include "src/tint/utils/map.h"
 
@@ -100,8 +100,8 @@
     // get_buffer_size_intrinsic() emits the function decorated with
     // BufferSizeIntrinsic that is transformed by the HLSL writer into a call to
     // [RW]ByteAddressBuffer.GetDimensions().
-    std::unordered_map<const sem::Reference*, Symbol> buffer_size_intrinsics;
-    auto get_buffer_size_intrinsic = [&](const sem::Reference* buffer_type) {
+    std::unordered_map<const type::Reference*, Symbol> buffer_size_intrinsics;
+    auto get_buffer_size_intrinsic = [&](const type::Reference* buffer_type) {
         return utils::GetOrCreate(buffer_size_intrinsics, buffer_type, [&] {
             auto name = b.Sym();
             auto* type = CreateASTTypeFor(ctx, buffer_type);
@@ -168,7 +168,7 @@
                         break;
                     }
                     auto* storage_buffer_var = storage_buffer_sem->Variable();
-                    auto* storage_buffer_type = storage_buffer_sem->Type()->As<sem::Reference>();
+                    auto* storage_buffer_type = storage_buffer_sem->Type()->As<type::Reference>();
 
                     // Generate BufferSizeIntrinsic for this storage type if we haven't already
                     auto buffer_size = get_buffer_size_intrinsic(storage_buffer_type);
diff --git a/src/tint/transform/decompose_memory_access.cc b/src/tint/transform/decompose_memory_access.cc
index 70cf830..4c5eda4 100644
--- a/src/tint/transform/decompose_memory_access.cc
+++ b/src/tint/transform/decompose_memory_access.cc
@@ -30,10 +30,10 @@
 #include "src/tint/sem/atomic.h"
 #include "src/tint/sem/call.h"
 #include "src/tint/sem/member_accessor_expression.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/sem/statement.h"
 #include "src/tint/sem/struct.h"
 #include "src/tint/sem/variable.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/utils/block_allocator.h"
 #include "src/tint/utils/hash.h"
 #include "src/tint/utils/map.h"
diff --git a/src/tint/transform/demote_to_helper.cc b/src/tint/transform/demote_to_helper.cc
index 9b44777..ab86fd9 100644
--- a/src/tint/transform/demote_to_helper.cc
+++ b/src/tint/transform/demote_to_helper.cc
@@ -22,9 +22,9 @@
 #include "src/tint/sem/block_statement.h"
 #include "src/tint/sem/call.h"
 #include "src/tint/sem/function.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/sem/statement.h"
 #include "src/tint/transform/utils/hoist_to_decl_before.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/utils/map.h"
 
 TINT_INSTANTIATE_TYPEINFO(tint::transform::DemoteToHelper);
@@ -123,7 +123,7 @@
                 }
 
                 // Skip writes to invocation-private address spaces.
-                auto* ref = sem.Get(assign->lhs)->Type()->As<sem::Reference>();
+                auto* ref = sem.Get(assign->lhs)->Type()->As<type::Reference>();
                 switch (ref->AddressSpace()) {
                     case ast::AddressSpace::kStorage:
                         // Need to mask these.
diff --git a/src/tint/transform/direct_variable_access.cc b/src/tint/transform/direct_variable_access.cc
index 78169d8..5f1ffc1 100644
--- a/src/tint/transform/direct_variable_access.cc
+++ b/src/tint/transform/direct_variable_access.cc
@@ -441,7 +441,7 @@
                     chain->root.variable = variable;
                     chain->root.type = variable->Type();
                     chain->root.address_space = variable->AddressSpace();
-                    if (auto* ptr = chain->root.type->As<sem::Pointer>()) {
+                    if (auto* ptr = chain->root.type->As<type::Pointer>()) {
                         chain->root.address_space = ptr->AddressSpace();
                     }
                     access_chains.Add(expr, chain);
@@ -456,13 +456,13 @@
                         }
                     },
                     [&](const ast::Parameter*) {
-                        if (variable->Type()->Is<sem::Pointer>()) {
+                        if (variable->Type()->Is<type::Pointer>()) {
                             // Start a new access chain for the pointer parameter access
                             create_new_chain();
                         }
                     },
                     [&](const ast::Let*) {
-                        if (variable->Type()->Is<sem::Pointer>()) {
+                        if (variable->Type()->Is<type::Pointer>()) {
                             // variable is a pointer-let.
                             auto* init = sem.Get(variable->Declaration()->initializer);
                             // Note: We do not use take_chain() here, as we need to preserve the
@@ -637,7 +637,7 @@
             for (size_t i = 0; i < call->Arguments().Length(); i++) {
                 const auto* arg = call->Arguments()[i];
                 const auto* param = target->Parameters()[i];
-                const auto* param_ty = param->Type()->As<sem::Pointer>();
+                const auto* param_ty = param->Type()->As<type::Pointer>();
                 if (!param_ty) {
                     continue;  // Parameter type is not a pointer.
                 }
@@ -880,7 +880,7 @@
             for (size_t arg_idx = 0; arg_idx < call->Arguments().Length(); arg_idx++) {
                 auto* arg = call->Arguments()[arg_idx];
                 auto* param = call->Target()->Parameters()[arg_idx];
-                auto* param_ty = param->Type()->As<sem::Pointer>();
+                auto* param_ty = param->Type()->As<type::Pointer>();
                 if (!param_ty) {
                     // Parameter is not a pointer.
                     // Just clone the unaltered argument.
@@ -1048,7 +1048,7 @@
 
             // BuildAccessExpr() always returns a non-pointer.
             // If the expression we're replacing is a pointer, take the address.
-            if (expr->Type()->Is<sem::Pointer>()) {
+            if (expr->Type()->Is<type::Pointer>()) {
                 chain_expr = b.AddressOf(chain_expr);
             }
 
@@ -1123,7 +1123,7 @@
 
         const ast::Expression* expr = b.Expr(ctx.Clone(root.variable->Declaration()->symbol));
         if (deref) {
-            if (root.variable->Type()->Is<sem::Pointer>()) {
+            if (root.variable->Type()->Is<type::Pointer>()) {
                 expr = b.Deref(expr);
             }
         }
@@ -1164,7 +1164,7 @@
     /// @returns true if the function @p fn has at least one pointer parameter.
     static bool HasPointerParameter(const sem::Function* fn) {
         for (auto* param : fn->Parameters()) {
-            if (param->Type()->Is<sem::Pointer>()) {
+            if (param->Type()->Is<type::Pointer>()) {
                 return true;
             }
         }
@@ -1176,7 +1176,7 @@
     /// generated, and must be stripped.
     static bool MustBeCalled(const sem::Function* fn) {
         for (auto* param : fn->Parameters()) {
-            if (auto* ptr = param->Type()->As<sem::Pointer>()) {
+            if (auto* ptr = param->Type()->As<type::Pointer>()) {
                 switch (ptr->AddressSpace()) {
                     case ast::AddressSpace::kUniform:
                     case ast::AddressSpace::kStorage:
diff --git a/src/tint/transform/localize_struct_array_assignment.cc b/src/tint/transform/localize_struct_array_assignment.cc
index f36dc7d..7096700 100644
--- a/src/tint/transform/localize_struct_array_assignment.cc
+++ b/src/tint/transform/localize_struct_array_assignment.cc
@@ -22,10 +22,10 @@
 #include "src/tint/program_builder.h"
 #include "src/tint/sem/expression.h"
 #include "src/tint/sem/member_accessor_expression.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/sem/statement.h"
 #include "src/tint/sem/variable.h"
 #include "src/tint/transform/simplify_pointers.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/utils/scoped_assignment.h"
 
 TINT_INSTANTIATE_TYPEINFO(tint::transform::LocalizeStructArrayAssignment);
@@ -183,9 +183,9 @@
         }
 
         auto* type = root_ident->Type();
-        if (auto* ref = type->As<sem::Reference>()) {
+        if (auto* ref = type->As<type::Reference>()) {
             return {ref->StoreType(), ref->AddressSpace()};
-        } else if (auto* ptr = type->As<sem::Pointer>()) {
+        } else if (auto* ptr = type->As<type::Pointer>()) {
             return {ptr->StoreType(), ptr->AddressSpace()};
         }
 
diff --git a/src/tint/transform/packed_vec3.cc b/src/tint/transform/packed_vec3.cc
index f4ceb76..2aba94d 100644
--- a/src/tint/transform/packed_vec3.cc
+++ b/src/tint/transform/packed_vec3.cc
@@ -100,7 +100,7 @@
                 [&](const sem::VariableUser* user) {
                     auto* v = user->Variable();
                     if (v->Declaration()->Is<ast::Let>() &&  // if variable is let...
-                        v->Type()->Is<sem::Pointer>() &&     // and let is a pointer...
+                        v->Type()->Is<type::Pointer>() &&    // and let is a pointer...
                         refs.Contains(v->Initializer())) {   // and pointer is to a packed vector...
                         refs.Add(user);  // then propagate tracking to pointer usage
                     }
diff --git a/src/tint/transform/preserve_padding.cc b/src/tint/transform/preserve_padding.cc
index 8f0f6d8..0dd3ea2 100644
--- a/src/tint/transform/preserve_padding.cc
+++ b/src/tint/transform/preserve_padding.cc
@@ -18,8 +18,8 @@
 #include <utility>
 
 #include "src/tint/program_builder.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/sem/struct.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/utils/map.h"
 #include "src/tint/utils/vector.h"
 
@@ -53,7 +53,7 @@
                         // Ignore phony assignment.
                         return;
                     }
-                    if (ty->As<sem::Reference>()->AddressSpace() != ast::AddressSpace::kStorage) {
+                    if (ty->As<type::Reference>()->AddressSpace() != ast::AddressSpace::kStorage) {
                         // We only care about assignments that write to variables in the storage
                         // address space, as nothing else is host-visible.
                         return;
diff --git a/src/tint/transform/robustness.cc b/src/tint/transform/robustness.cc
index 2c7925b..93edec1 100644
--- a/src/tint/transform/robustness.cc
+++ b/src/tint/transform/robustness.cc
@@ -23,8 +23,8 @@
 #include "src/tint/sem/call.h"
 #include "src/tint/sem/expression.h"
 #include "src/tint/sem/index_accessor_expression.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/sem/statement.h"
+#include "src/tint/type/reference.h"
 
 TINT_INSTANTIATE_TYPEINFO(tint::transform::Robustness);
 TINT_INSTANTIATE_TYPEINFO(tint::transform::Robustness::Config);
@@ -70,7 +70,7 @@
         auto* sem = src->Sem().Get(expr)->UnwrapMaterialize()->As<sem::IndexAccessorExpression>();
         auto* ret_type = sem->Type();
 
-        auto* ref = ret_type->As<sem::Reference>();
+        auto* ref = ret_type->As<type::Reference>();
         if (ref && omitted_address_spaces.count(ref->AddressSpace()) != 0) {
             return nullptr;
         }
diff --git a/src/tint/transform/simplify_pointers.cc b/src/tint/transform/simplify_pointers.cc
index a0855b7..5d36c1d 100644
--- a/src/tint/transform/simplify_pointers.cc
+++ b/src/tint/transform/simplify_pointers.cc
@@ -115,7 +115,7 @@
                 auto* var = user->Variable();
                 if (var->Is<sem::LocalVariable>() &&       //
                     var->Declaration()->Is<ast::Let>() &&  //
-                    var->Type()->Is<sem::Pointer>()) {
+                    var->Type()->Is<type::Pointer>()) {
                     op.expr = var->Declaration()->initializer;
                     continue;
                 }
@@ -170,7 +170,7 @@
                 }
 
                 auto* var = ctx.src->Sem().Get(let->variable);
-                if (!var->Type()->Is<sem::Pointer>()) {
+                if (!var->Type()->Is<type::Pointer>()) {
                     continue;  // Not a pointer type. Ignore.
                 }
 
diff --git a/src/tint/transform/spirv_atomic.cc b/src/tint/transform/spirv_atomic.cc
index 8bf1836..6ee58b5 100644
--- a/src/tint/transform/spirv_atomic.cc
+++ b/src/tint/transform/spirv_atomic.cc
@@ -25,8 +25,8 @@
 #include "src/tint/sem/function.h"
 #include "src/tint/sem/index_accessor_expression.h"
 #include "src/tint/sem/member_accessor_expression.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/sem/statement.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/utils/map.h"
 #include "src/tint/utils/unique_vector.h"
 
@@ -218,11 +218,11 @@
                 }
                 return b.ty.array(AtomicTypeFor(arr->ElemType()), u32(count.value()));
             },
-            [&](const sem::Pointer* ptr) {
+            [&](const type::Pointer* ptr) {
                 return b.ty.pointer(AtomicTypeFor(ptr->StoreType()), ptr->AddressSpace(),
                                     ptr->Access());
             },
-            [&](const sem::Reference* ref) { return AtomicTypeFor(ref->StoreType()); },
+            [&](const type::Reference* ref) { return AtomicTypeFor(ref->StoreType()); },
             [&](Default) {
                 TINT_ICE(Transform, b.Diagnostics())
                     << "unhandled type: " << ty->FriendlyName(ctx.src->Symbols());
@@ -233,7 +233,7 @@
     void ReplaceLoadsAndStores() {
         // Returns true if 'e' is a reference to an atomic variable or struct member
         auto is_ref_to_atomic_var = [&](const sem::Expression* e) {
-            if (tint::Is<sem::Reference>(e->Type()) && e->RootIdentifier() &&
+            if (tint::Is<type::Reference>(e->Type()) && e->RootIdentifier() &&
                 (atomic_variables.count(e->RootIdentifier()) != 0)) {
                 // If it's a struct member, make sure it's one we marked as atomic
                 if (auto* ma = e->As<sem::StructMemberAccess>()) {
diff --git a/src/tint/transform/std140.cc b/src/tint/transform/std140.cc
index dab3eb1..d2e9349 100644
--- a/src/tint/transform/std140.cc
+++ b/src/tint/transform/std140.cc
@@ -516,7 +516,7 @@
                         access.indices.Push(UniformVariable{});
                         return Action::kStop;
                     }
-                    if (user->Variable()->Type()->Is<sem::Pointer>()) {
+                    if (user->Variable()->Type()->Is<type::Pointer>()) {
                         // Found a pointer. As the root identifier is a uniform buffer variable,
                         // this must be a pointer-let. Continue traversing from the let
                         // initializer.
diff --git a/src/tint/transform/transform.cc b/src/tint/transform/transform.cc
index 85448f7..1be2758 100644
--- a/src/tint/transform/transform.cc
+++ b/src/tint/transform/transform.cc
@@ -21,9 +21,9 @@
 #include "src/tint/sem/atomic.h"
 #include "src/tint/sem/block_statement.h"
 #include "src/tint/sem/for_loop_statement.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/sem/variable.h"
 #include "src/tint/type/depth_multisampled_texture.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/type/sampler.h"
 
 TINT_INSTANTIATE_TYPEINFO(tint::transform::Transform);
@@ -139,7 +139,7 @@
     if (auto* s = ty->As<sem::Struct>()) {
         return ctx.dst->create<ast::TypeName>(ctx.Clone(s->Declaration()->name));
     }
-    if (auto* s = ty->As<sem::Reference>()) {
+    if (auto* s = ty->As<type::Reference>()) {
         return CreateASTTypeFor(ctx, s->StoreType());
     }
     if (auto* a = ty->As<sem::Atomic>()) {
diff --git a/src/tint/transform/utils/hoist_to_decl_before.cc b/src/tint/transform/utils/hoist_to_decl_before.cc
index ede1986..fa18934 100644
--- a/src/tint/transform/utils/hoist_to_decl_before.cc
+++ b/src/tint/transform/utils/hoist_to_decl_before.cc
@@ -20,9 +20,9 @@
 #include "src/tint/sem/block_statement.h"
 #include "src/tint/sem/for_loop_statement.h"
 #include "src/tint/sem/if_statement.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/sem/variable.h"
 #include "src/tint/sem/while_statement.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/utils/hashmap.h"
 #include "src/tint/utils/reverse.h"
 #include "src/tint/utils/transform.h"
diff --git a/src/tint/sem/pointer.cc b/src/tint/type/pointer.cc
similarity index 83%
rename from src/tint/sem/pointer.cc
rename to src/tint/type/pointer.cc
index 54dd3a6..37dbf69 100644
--- a/src/tint/sem/pointer.cc
+++ b/src/tint/type/pointer.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Tint Authors.
+// Copyright 2022 The Tint Authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,20 +12,20 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "src/tint/sem/pointer.h"
+#include "src/tint/type/pointer.h"
 
 #include "src/tint/program_builder.h"
-#include "src/tint/sem/reference.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/utils/hash.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::sem::Pointer);
+TINT_INSTANTIATE_TYPEINFO(tint::type::Pointer);
 
-namespace tint::sem {
+namespace tint::type {
 
 Pointer::Pointer(const type::Type* subtype, ast::AddressSpace address_space, ast::Access access)
     : Base(type::TypeFlags{}), subtype_(subtype), address_space_(address_space), access_(access) {
-    TINT_ASSERT(Semantic, !subtype->Is<Reference>());
-    TINT_ASSERT(Semantic, access != ast::Access::kUndefined);
+    TINT_ASSERT(Type, !subtype->Is<Reference>());
+    TINT_ASSERT(Type, access != ast::Access::kUndefined);
 }
 
 size_t Pointer::Hash() const {
@@ -55,4 +55,4 @@
 
 Pointer::~Pointer() = default;
 
-}  // namespace tint::sem
+}  // namespace tint::type
diff --git a/src/tint/sem/pointer.h b/src/tint/type/pointer.h
similarity index 91%
rename from src/tint/sem/pointer.h
rename to src/tint/type/pointer.h
index 4af26ed..0828046 100644
--- a/src/tint/sem/pointer.h
+++ b/src/tint/type/pointer.h
@@ -1,4 +1,4 @@
-// Copyright 2020 The Tint Authors.
+// Copyright 2022 The Tint Authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef SRC_TINT_SEM_POINTER_H_
-#define SRC_TINT_SEM_POINTER_H_
+#ifndef SRC_TINT_TYPE_POINTER_H_
+#define SRC_TINT_TYPE_POINTER_H_
 
 #include <string>
 
@@ -21,7 +21,7 @@
 #include "src/tint/ast/address_space.h"
 #include "src/tint/type/type.h"
 
-namespace tint::sem {
+namespace tint::type {
 
 /// A pointer type.
 class Pointer final : public Castable<Pointer, type::Type> {
@@ -63,6 +63,6 @@
     ast::Access const access_;
 };
 
-}  // namespace tint::sem
+}  // namespace tint::type
 
-#endif  // SRC_TINT_SEM_POINTER_H_
+#endif  // SRC_TINT_TYPE_POINTER_H_
diff --git a/src/tint/sem/pointer_test.cc b/src/tint/type/pointer_test.cc
similarity index 96%
rename from src/tint/sem/pointer_test.cc
rename to src/tint/type/pointer_test.cc
index c5201ff..ebfb895 100644
--- a/src/tint/sem/pointer_test.cc
+++ b/src/tint/type/pointer_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2020 The Tint Authors.
+// Copyright 2022 The Tint Authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,10 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "src/tint/sem/test_helper.h"
+#include "src/tint/type/test_helper.h"
 #include "src/tint/type/texture.h"
 
-namespace tint::sem {
+namespace tint::type {
 namespace {
 
 using PointerTest = TestHelper;
@@ -88,4 +88,4 @@
 }
 
 }  // namespace
-}  // namespace tint::sem
+}  // namespace tint::type
diff --git a/src/tint/sem/reference.cc b/src/tint/type/reference.cc
similarity index 84%
rename from src/tint/sem/reference.cc
rename to src/tint/type/reference.cc
index e5193e8..475c80e 100644
--- a/src/tint/sem/reference.cc
+++ b/src/tint/type/reference.cc
@@ -1,4 +1,4 @@
-// Copyright 2021 The Tint Authors.
+// Copyright 2022 The Tint Authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,19 +12,19 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "src/tint/sem/reference.h"
+#include "src/tint/type/reference.h"
 
 #include "src/tint/program_builder.h"
 #include "src/tint/utils/hash.h"
 
-TINT_INSTANTIATE_TYPEINFO(tint::sem::Reference);
+TINT_INSTANTIATE_TYPEINFO(tint::type::Reference);
 
-namespace tint::sem {
+namespace tint::type {
 
 Reference::Reference(const type::Type* subtype, ast::AddressSpace address_space, ast::Access access)
     : Base(type::TypeFlags{}), subtype_(subtype), address_space_(address_space), access_(access) {
-    TINT_ASSERT(Semantic, !subtype->Is<Reference>());
-    TINT_ASSERT(Semantic, access != ast::Access::kUndefined);
+    TINT_ASSERT(Type, !subtype->Is<Reference>());
+    TINT_ASSERT(Type, access != ast::Access::kUndefined);
 }
 
 size_t Reference::Hash() const {
@@ -54,4 +54,4 @@
 
 Reference::~Reference() = default;
 
-}  // namespace tint::sem
+}  // namespace tint::type
diff --git a/src/tint/sem/reference.h b/src/tint/type/reference.h
similarity index 91%
rename from src/tint/sem/reference.h
rename to src/tint/type/reference.h
index ba74f33..94db9c4 100644
--- a/src/tint/sem/reference.h
+++ b/src/tint/type/reference.h
@@ -1,4 +1,4 @@
-// Copyright 2021 The Tint Authors.
+// Copyright 2022 The Tint Authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef SRC_TINT_SEM_REFERENCE_H_
-#define SRC_TINT_SEM_REFERENCE_H_
+#ifndef SRC_TINT_TYPE_REFERENCE_H_
+#define SRC_TINT_TYPE_REFERENCE_H_
 
 #include <string>
 
@@ -21,7 +21,7 @@
 #include "src/tint/ast/address_space.h"
 #include "src/tint/type/type.h"
 
-namespace tint::sem {
+namespace tint::type {
 
 /// A reference type.
 class Reference final : public Castable<Reference, type::Type> {
@@ -63,6 +63,6 @@
     ast::Access const access_;
 };
 
-}  // namespace tint::sem
+}  // namespace tint::type
 
-#endif  // SRC_TINT_SEM_REFERENCE_H_
+#endif  // SRC_TINT_TYPE_REFERENCE_H_
diff --git a/src/tint/sem/reference_test.cc b/src/tint/type/reference_test.cc
similarity index 95%
rename from src/tint/sem/reference_test.cc
rename to src/tint/type/reference_test.cc
index 3ead233..b5f06b4 100644
--- a/src/tint/sem/reference_test.cc
+++ b/src/tint/type/reference_test.cc
@@ -1,4 +1,4 @@
-// Copyright 2021 The Tint Authors.
+// Copyright 2022 The Tint Authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,10 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "src/tint/sem/reference.h"
-#include "src/tint/sem/test_helper.h"
+#include "src/tint/type/reference.h"
+#include "src/tint/type/test_helper.h"
 
-namespace tint::sem {
+namespace tint::type {
 namespace {
 
 using ReferenceTest = TestHelper;
@@ -91,4 +91,4 @@
 }
 
 }  // namespace
-}  // namespace tint::sem
+}  // namespace tint::type
diff --git a/src/tint/type/type.cc b/src/tint/type/type.cc
index 61bb3dd..43026e1 100644
--- a/src/tint/type/type.cc
+++ b/src/tint/type/type.cc
@@ -16,8 +16,6 @@
 
 #include "src/tint/sem/array.h"
 #include "src/tint/sem/matrix.h"
-#include "src/tint/sem/pointer.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/sem/struct.h"
 #include "src/tint/sem/vector.h"
 #include "src/tint/type/abstract_float.h"
@@ -26,6 +24,8 @@
 #include "src/tint/type/f16.h"
 #include "src/tint/type/f32.h"
 #include "src/tint/type/i32.h"
+#include "src/tint/type/pointer.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/type/sampler.h"
 #include "src/tint/type/texture.h"
 #include "src/tint/type/u32.h"
@@ -46,7 +46,7 @@
 
 const Type* Type::UnwrapPtr() const {
     auto* type = this;
-    while (auto* ptr = type->As<sem::Pointer>()) {
+    while (auto* ptr = type->As<type::Pointer>()) {
         type = ptr->StoreType();
     }
     return type;
@@ -54,7 +54,7 @@
 
 const Type* Type::UnwrapRef() const {
     auto* type = this;
-    if (auto* ref = type->As<sem::Reference>()) {
+    if (auto* ref = type->As<type::Reference>()) {
         type = ref->StoreType();
     }
     return type;
diff --git a/src/tint/type/type_test.cc b/src/tint/type/type_test.cc
index 4b08300..60fb6c7 100644
--- a/src/tint/type/type_test.cc
+++ b/src/tint/type/type_test.cc
@@ -12,11 +12,11 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "src/tint/sem/reference.h"
 #include "src/tint/type/abstract_float.h"
 #include "src/tint/type/abstract_int.h"
 #include "src/tint/type/array_count.h"
 #include "src/tint/type/f16.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/type/test_helper.h"
 
 namespace tint::type {
@@ -43,8 +43,8 @@
     const sem::Matrix* mat4x3_f32 = create<sem::Matrix>(vec3_f32, 4u);
     const sem::Matrix* mat4x3_f16 = create<sem::Matrix>(vec3_f16, 4u);
     const sem::Matrix* mat4x3_af = create<sem::Matrix>(vec3_af, 4u);
-    const sem::Reference* ref_u32 =
-        create<sem::Reference>(u32, ast::AddressSpace::kPrivate, ast::Access::kReadWrite);
+    const type::Reference* ref_u32 =
+        create<type::Reference>(u32, ast::AddressSpace::kPrivate, ast::Access::kReadWrite);
     const sem::Struct* str_f32 = create<sem::Struct>(nullptr,
                                                      Source{},
                                                      Sym("str_f32"),
diff --git a/src/tint/writer/glsl/generator_impl.cc b/src/tint/writer/glsl/generator_impl.cc
index ea43943..80f5f77 100644
--- a/src/tint/writer/glsl/generator_impl.cc
+++ b/src/tint/writer/glsl/generator_impl.cc
@@ -1939,7 +1939,7 @@
 
             auto const* type = v->Type();
 
-            if (auto* ptr = type->As<sem::Pointer>()) {
+            if (auto* ptr = type->As<type::Pointer>()) {
                 // Transform pointer parameters in to `inout` parameters.
                 // The WGSL spec is highly restrictive in what can be passed in pointer
                 // parameters, which allows for this transformation. See:
@@ -2888,7 +2888,7 @@
         if (mat->rows() != mat->columns()) {
             out << "x" << mat->rows();
         }
-    } else if (type->Is<sem::Pointer>()) {
+    } else if (type->Is<type::Pointer>()) {
         TINT_ICE(Writer, diagnostics_)
             << "Attempting to emit pointer type. These should have been removed "
                "with the InlinePointerLets transform";
@@ -3159,7 +3159,7 @@
                     }
                     auto param_name = "param_" + std::to_string(parameter_names.size());
                     const auto* ty = param->Type();
-                    if (auto* ptr = ty->As<sem::Pointer>()) {
+                    if (auto* ptr = ty->As<type::Pointer>()) {
                         decl << "inout ";
                         ty = ptr->StoreType();
                     }
diff --git a/src/tint/writer/hlsl/generator_impl.cc b/src/tint/writer/hlsl/generator_impl.cc
index 565f97a..2b46e57 100644
--- a/src/tint/writer/hlsl/generator_impl.cc
+++ b/src/tint/writer/hlsl/generator_impl.cc
@@ -2883,7 +2883,7 @@
             auto address_space = ast::AddressSpace::kNone;
             auto access = ast::Access::kUndefined;
 
-            if (auto* ptr = type->As<sem::Pointer>()) {
+            if (auto* ptr = type->As<type::Pointer>()) {
                 type = ptr->StoreType();
                 switch (ptr->AddressSpace()) {
                     case ast::AddressSpace::kStorage:
@@ -3993,7 +3993,7 @@
             out << mat->columns() << "x" << mat->rows();
             return true;
         },
-        [&](const sem::Pointer*) {
+        [&](const type::Pointer*) {
             TINT_ICE(Writer, diagnostics_)
                 << "Attempting to emit pointer type. These should have been "
                    "removed with the InlinePointerLets transform";
@@ -4311,7 +4311,7 @@
                     }
                     auto param_name = "param_" + std::to_string(parameter_names.size());
                     const auto* ty = param->Type();
-                    if (auto* ptr = ty->As<sem::Pointer>()) {
+                    if (auto* ptr = ty->As<type::Pointer>()) {
                         decl << "inout ";
                         ty = ptr->StoreType();
                     }
diff --git a/src/tint/writer/msl/generator_impl.cc b/src/tint/writer/msl/generator_impl.cc
index 7b19a26..a6659d2 100644
--- a/src/tint/writer/msl/generator_impl.cc
+++ b/src/tint/writer/msl/generator_impl.cc
@@ -39,8 +39,6 @@
 #include "src/tint/sem/matrix.h"
 #include "src/tint/sem/member_accessor_expression.h"
 #include "src/tint/sem/module.h"
-#include "src/tint/sem/pointer.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/sem/struct.h"
 #include "src/tint/sem/switch_statement.h"
 #include "src/tint/sem/type_conversion.h"
@@ -71,6 +69,8 @@
 #include "src/tint/type/f32.h"
 #include "src/tint/type/i32.h"
 #include "src/tint/type/multisampled_texture.h"
+#include "src/tint/type/pointer.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/type/sampled_texture.h"
 #include "src/tint/type/storage_texture.h"
 #include "src/tint/type/u32.h"
@@ -907,7 +907,7 @@
             return call("atomic_exchange_explicit", true);
 
         case sem::BuiltinType::kAtomicCompareExchangeWeak: {
-            auto* ptr_ty = TypeOf(expr->args[0])->UnwrapRef()->As<sem::Pointer>();
+            auto* ptr_ty = TypeOf(expr->args[0])->UnwrapRef()->As<type::Pointer>();
             auto sc = ptr_ty->AddressSpace();
             auto* str = builtin->ReturnType()->As<sem::Struct>();
 
@@ -1884,7 +1884,7 @@
                 return false;
             }
             // Parameter name is output as part of the type for pointers.
-            if (!type->Is<sem::Pointer>()) {
+            if (!type->Is<type::Pointer>()) {
                 out << " " << program_->Symbols().NameFor(v->symbol);
             }
         }
@@ -2011,7 +2011,7 @@
                 return false;
             }
             // Parameter name is output as part of the type for pointers.
-            if (!type->Is<sem::Pointer>()) {
+            if (!type->Is<type::Pointer>()) {
                 out << " " << param_name;
             }
 
@@ -2580,7 +2580,7 @@
             out << mat->columns() << "x" << mat->rows();
             return true;
         },
-        [&](const sem::Pointer* ptr) {
+        [&](const type::Pointer* ptr) {
             if (ptr->Access() == ast::Access::kRead) {
                 out << "const ";
             }
@@ -3016,7 +3016,7 @@
         return false;
     }
     // Variable name is output as part of the type for pointers.
-    if (!type->Is<sem::Pointer>()) {
+    if (!type->Is<type::Pointer>()) {
         out << " " << name;
     }
 
@@ -3066,7 +3066,7 @@
     }
 
     // Variable name is output as part of the type for pointers.
-    if (!type->Is<sem::Pointer>()) {
+    if (!type->Is<type::Pointer>()) {
         out << " " << name;
     }
 
diff --git a/src/tint/writer/msl/generator_impl_type_test.cc b/src/tint/writer/msl/generator_impl_type_test.cc
index c7d62e0..12d234c 100644
--- a/src/tint/writer/msl/generator_impl_type_test.cc
+++ b/src/tint/writer/msl/generator_impl_type_test.cc
@@ -211,7 +211,7 @@
 
 TEST_F(MslGeneratorImplTest, EmitType_Pointer) {
     auto* f32 = create<type::F32>();
-    auto* p = create<sem::Pointer>(f32, ast::AddressSpace::kWorkgroup, ast::Access::kReadWrite);
+    auto* p = create<type::Pointer>(f32, ast::AddressSpace::kWorkgroup, ast::Access::kReadWrite);
 
     GeneratorImpl& gen = Build();
 
diff --git a/src/tint/writer/spirv/builder.cc b/src/tint/writer/spirv/builder.cc
index 3b9b177..8cdee56 100644
--- a/src/tint/writer/spirv/builder.cc
+++ b/src/tint/writer/spirv/builder.cc
@@ -31,7 +31,6 @@
 #include "src/tint/sem/materialize.h"
 #include "src/tint/sem/member_accessor_expression.h"
 #include "src/tint/sem/module.h"
-#include "src/tint/sem/reference.h"
 #include "src/tint/sem/statement.h"
 #include "src/tint/sem/struct.h"
 #include "src/tint/sem/switch_statement.h"
@@ -43,6 +42,7 @@
 #include "src/tint/type/depth_multisampled_texture.h"
 #include "src/tint/type/depth_texture.h"
 #include "src/tint/type/multisampled_texture.h"
+#include "src/tint/type/reference.h"
 #include "src/tint/type/sampled_texture.h"
 #include "src/tint/utils/defer.h"
 #include "src/tint/utils/map.h"
@@ -882,7 +882,7 @@
     // If the source is a reference, we access chain into it.
     // In the future, pointers may support access-chaining.
     // See https://github.com/gpuweb/gpuweb/pull/1580
-    if (info->source_type->Is<sem::Reference>()) {
+    if (info->source_type->Is<type::Reference>()) {
         info->access_chain_indices.push_back(idx_id);
         info->source_type = TypeOf(expr);
         return true;
@@ -942,7 +942,7 @@
     if (auto* access = expr_sem->As<sem::StructMemberAccess>()) {
         uint32_t idx = access->Member()->Index();
 
-        if (info->source_type->Is<sem::Reference>()) {
+        if (info->source_type->Is<type::Reference>()) {
             auto idx_id = GenerateConstantIfNeeded(ScalarConstant::U32(idx));
             if (idx_id == 0) {
                 return 0;
@@ -974,7 +974,7 @@
         // Single element swizzle is either an access chain or a composite extract
         auto& indices = swizzle->Indices();
         if (indices.Length() == 1) {
-            if (info->source_type->Is<sem::Reference>()) {
+            if (info->source_type->Is<type::Reference>()) {
                 auto idx_id = GenerateConstantIfNeeded(ScalarConstant::U32(indices[0]));
                 if (idx_id == 0) {
                     return 0;
@@ -1158,7 +1158,7 @@
 }
 
 uint32_t Builder::GenerateLoadIfNeeded(const type::Type* type, uint32_t id) {
-    if (auto* ref = type->As<sem::Reference>()) {
+    if (auto* ref = type->As<type::Reference>()) {
         type = ref->StoreType();
     } else {
         return id;
@@ -1901,8 +1901,8 @@
 uint32_t Builder::GenerateSplat(uint32_t scalar_id, const type::Type* vec_type) {
     // Create a new vector to splat scalar into
     auto splat_vector = result_op();
-    auto* splat_vector_type = builder_.create<sem::Pointer>(vec_type, ast::AddressSpace::kFunction,
-                                                            ast::Access::kReadWrite);
+    auto* splat_vector_type = builder_.create<type::Pointer>(vec_type, ast::AddressSpace::kFunction,
+                                                             ast::Access::kReadWrite);
     push_function_var({Operand(GenerateTypeIfNeeded(splat_vector_type)), splat_vector,
                        U32Operand(ConvertAddressSpace(ast::AddressSpace::kFunction)),
                        Operand(GenerateConstantNullIfNeeded(vec_type))});
@@ -2329,7 +2329,7 @@
             return 0;
         }
 
-        if (generate_load && !param->Type()->Is<sem::Pointer>()) {
+        if (generate_load && !param->Type()->Is<type::Pointer>()) {
             val_id = GenerateLoadIfNeeded(arg->Type(), val_id);
         }
         return val_id;
@@ -3070,10 +3070,10 @@
                                     Operand result_id) {
     auto is_value_signed = [&] { return builtin->Parameters()[1]->Type()->Is<type::I32>(); };
 
-    auto address_space = builtin->Parameters()[0]->Type()->As<sem::Pointer>()->AddressSpace();
+    auto address_space = builtin->Parameters()[0]->Type()->As<type::Pointer>()->AddressSpace();
 
     uint32_t memory_id = 0;
-    switch (builtin->Parameters()[0]->Type()->As<sem::Pointer>()->AddressSpace()) {
+    switch (builtin->Parameters()[0]->Type()->As<type::Pointer>()->AddressSpace()) {
         case ast::AddressSpace::kWorkgroup:
             memory_id = GenerateConstantIfNeeded(
                 ScalarConstant::U32(static_cast<uint32_t>(spv::Scope::Workgroup)));
@@ -3660,12 +3660,12 @@
     // definitions in the generated SPIR-V. Note that nested pointers and
     // references are not legal in WGSL, so only considering the top-level type is
     // fine.
-    if (auto* ptr = type->As<sem::Pointer>()) {
-        type = builder_.create<sem::Pointer>(ptr->StoreType(), ptr->AddressSpace(),
-                                             ast::Access::kReadWrite);
-    } else if (auto* ref = type->As<sem::Reference>()) {
-        type = builder_.create<sem::Pointer>(ref->StoreType(), ref->AddressSpace(),
-                                             ast::Access::kReadWrite);
+    if (auto* ptr = type->As<type::Pointer>()) {
+        type = builder_.create<type::Pointer>(ptr->StoreType(), ptr->AddressSpace(),
+                                              ast::Access::kReadWrite);
+    } else if (auto* ref = type->As<type::Reference>()) {
+        type = builder_.create<type::Pointer>(ref->StoreType(), ref->AddressSpace(),
+                                              ast::Access::kReadWrite);
     }
 
     return utils::GetOrCreate(type_to_id_, type, [&]() -> uint32_t {
@@ -3695,10 +3695,10 @@
             [&](const sem::Matrix* mat) {  //
                 return GenerateMatrixType(mat, result);
             },
-            [&](const sem::Pointer* ptr) {  //
+            [&](const type::Pointer* ptr) {  //
                 return GeneratePointerType(ptr, result);
             },
-            [&](const sem::Reference* ref) {  //
+            [&](const type::Reference* ref) {  //
                 return GenerateReferenceType(ref, result);
             },
             [&](const sem::Struct* str) {  //
@@ -3878,7 +3878,7 @@
     return true;
 }
 
-bool Builder::GeneratePointerType(const sem::Pointer* ptr, const Operand& result) {
+bool Builder::GeneratePointerType(const type::Pointer* ptr, const Operand& result) {
     auto subtype_id = GenerateTypeIfNeeded(ptr->StoreType());
     if (subtype_id == 0) {
         return false;
@@ -3895,7 +3895,7 @@
     return true;
 }
 
-bool Builder::GenerateReferenceType(const sem::Reference* ref, const Operand& result) {
+bool Builder::GenerateReferenceType(const type::Reference* ref, const Operand& result) {
     auto subtype_id = GenerateTypeIfNeeded(ref->StoreType());
     if (subtype_id == 0) {
         return false;
diff --git a/src/tint/writer/spirv/builder.h b/src/tint/writer/spirv/builder.h
index 21dcf83..c5b07ce 100644
--- a/src/tint/writer/spirv/builder.h
+++ b/src/tint/writer/spirv/builder.h
@@ -44,10 +44,12 @@
 namespace tint::sem {
 class Call;
 class Constant;
-class Reference;
 class TypeInitializer;
 class TypeConversion;
 }  // namespace tint::sem
+namespace tint::type {
+class Reference;
+}  // namespace tint::type
 
 namespace tint::writer::spirv {
 
@@ -488,12 +490,12 @@
     /// @param ptr the pointer type to generate
     /// @param result the result operand
     /// @returns true if the pointer was successfully generated
-    bool GeneratePointerType(const sem::Pointer* ptr, const Operand& result);
+    bool GeneratePointerType(const type::Pointer* ptr, const Operand& result);
     /// Generates a reference type declaration
     /// @param ref the reference type to generate
     /// @param result the result operand
     /// @returns true if the reference was successfully generated
-    bool GenerateReferenceType(const sem::Reference* ref, const Operand& result);
+    bool GenerateReferenceType(const type::Reference* ref, const Operand& result);
     /// Generates a vector type declaration
     /// @param struct_type the vector to generate
     /// @param result the result operand
diff --git a/src/tint/writer/spirv/builder_type_test.cc b/src/tint/writer/spirv/builder_type_test.cc
index ca0aa47..ef632a1 100644
--- a/src/tint/writer/spirv/builder_type_test.cc
+++ b/src/tint/writer/spirv/builder_type_test.cc
@@ -293,7 +293,7 @@
 
 TEST_F(BuilderTest_Type, GeneratePtr) {
     auto* i32 = create<type::I32>();
-    auto* ptr = create<sem::Pointer>(i32, ast::AddressSpace::kOut, ast::Access::kReadWrite);
+    auto* ptr = create<type::Pointer>(i32, ast::AddressSpace::kOut, ast::Access::kReadWrite);
 
     spirv::Builder& b = Build();
 
@@ -308,7 +308,7 @@
 
 TEST_F(BuilderTest_Type, ReturnsGeneratedPtr) {
     auto* i32 = create<type::I32>();
-    auto* ptr = create<sem::Pointer>(i32, ast::AddressSpace::kOut, ast::Access::kReadWrite);
+    auto* ptr = create<type::Pointer>(i32, ast::AddressSpace::kOut, ast::Access::kReadWrite);
 
     spirv::Builder& b = Build();