Context object owns a TypeManager

Add a Context::Reset method to clear state.

Hide the member behind an accessor.

Change-Id: Iafb7c39249f66f70c5a99a8ed1c69f2c0238834f
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/17742
Reviewed-by: dan sinclair <dsinclair@google.com>
diff --git a/samples/main.cc b/samples/main.cc
index 5866646..2937852 100644
--- a/samples/main.cc
+++ b/samples/main.cc
@@ -252,10 +252,7 @@
     return 1;
   }
 
-  tint::TypeManager type_manager;
-
   tint::Context ctx;
-  ctx.type_mgr = &type_manager;
 
   std::unique_ptr<tint::reader::Reader> reader;
 #if TINT_BUILD_WGSL_READER
@@ -267,7 +264,7 @@
       return 1;
     }
     reader = std::make_unique<tint::reader::wgsl::Parser>(
-        ctx, std::string(data.begin(), data.end()));
+        &ctx, std::string(data.begin(), data.end()));
   }
 #endif  // TINT_BUILD_WGSL_READER
 
@@ -279,7 +276,7 @@
     if (!ReadFile<uint32_t>(options.input_filename, &data)) {
       return 1;
     }
-    reader = std::make_unique<tint::reader::spirv::Parser>(ctx, data);
+    reader = std::make_unique<tint::reader::spirv::Parser>(&ctx, data);
   }
 #endif  // TINT_BUILD_SPV_READER
 
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index dc37b6e..8f45236 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -181,6 +181,8 @@
   ast/variable_decoration.h
   ast/variable_statement.cc
   ast/variable_statement.h
+  context.h
+  context.cc
   reader/reader.cc
   reader/reader.h
   source.h
diff --git a/src/context.cc b/src/context.cc
new file mode 100644
index 0000000..4285eb4
--- /dev/null
+++ b/src/context.cc
@@ -0,0 +1,31 @@
+// Copyright 2020 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.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "src/context.h"
+
+#include <utility>
+
+#include "src/type_manager.h"
+
+namespace tint {
+
+Context::Context() = default;
+
+Context::~Context() = default;
+
+void Context::Reset() {
+  type_mgr_.Reset();
+}
+
+}  // namespace tint
diff --git a/src/context.h b/src/context.h
index d6d094f..f0495f2 100644
--- a/src/context.h
+++ b/src/context.h
@@ -21,9 +21,19 @@
 
 /// Context object for Tint. Holds various global resources used through
 /// the system.
-struct Context {
-  /// Manager to hold all of the various type objects
-  TypeManager* type_mgr = nullptr;
+class Context {
+ public:
+  /// Constructs a context with an empty type manager.
+  Context();
+  /// Destructor
+  ~Context();
+  /// Resets the state of this context.
+  void Reset();
+
+  TypeManager& type_mgr() { return type_mgr_; }
+
+ private:
+  TypeManager type_mgr_;
 };
 
 }  // namespace tint
diff --git a/src/reader/reader.cc b/src/reader/reader.cc
index 064482e..c94f899 100644
--- a/src/reader/reader.cc
+++ b/src/reader/reader.cc
@@ -17,7 +17,7 @@
 namespace tint {
 namespace reader {
 
-Reader::Reader(const Context& ctx) : ctx_(ctx) {}
+Reader::Reader(Context* ctx) : ctx_(*ctx) {}
 
 Reader::~Reader() = default;
 
diff --git a/src/reader/reader.h b/src/reader/reader.h
index a3dbbf5..6b1fd01 100644
--- a/src/reader/reader.h
+++ b/src/reader/reader.h
@@ -42,15 +42,15 @@
 
  protected:
   /// Constructor
-  /// @param ctx the context object
-  explicit Reader(const Context& ctx);
+  /// @param ctx the context object, must be non-null
+  explicit Reader(Context* ctx);
 
   /// Sets the error string
   /// @param msg the error message
   void set_error(const std::string& msg) { error_ = msg; }
 
   /// The Tint context object
-  const Context& ctx_;
+  Context& ctx_;
 
   /// An error message, if an error was encountered
   std::string error_;
diff --git a/src/reader/spirv/parser.cc b/src/reader/spirv/parser.cc
index 8b3bd44..c283cae 100644
--- a/src/reader/spirv/parser.cc
+++ b/src/reader/spirv/parser.cc
@@ -20,7 +20,7 @@
 namespace reader {
 namespace spirv {
 
-Parser::Parser(const Context& ctx, const std::vector<uint32_t>& spv_binary)
+Parser::Parser(Context* ctx, const std::vector<uint32_t>& spv_binary)
     : Reader(ctx), impl_(std::make_unique<ParserImpl>(ctx, spv_binary)) {}
 
 Parser::~Parser() = default;
diff --git a/src/reader/spirv/parser.h b/src/reader/spirv/parser.h
index d5c41c2..d4d0974 100644
--- a/src/reader/spirv/parser.h
+++ b/src/reader/spirv/parser.h
@@ -31,9 +31,9 @@
 class Parser : public Reader {
  public:
   /// Creates a new parser
-  /// @param ctx the context object
+  /// @param ctx the non-null context object
   /// @param input the input data to parse
-  Parser(const Context& ctx, const std::vector<uint32_t>& input);
+  Parser(Context* ctx, const std::vector<uint32_t>& input);
   /// Destructor
   ~Parser() override;
 
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index 97ce5f2..1f6b6d4 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -44,8 +44,7 @@
 
 }  // namespace
 
-ParserImpl::ParserImpl(const Context& ctx,
-                       const std::vector<uint32_t>& spv_binary)
+ParserImpl::ParserImpl(Context* ctx, const std::vector<uint32_t>& spv_binary)
     : Reader(ctx),
       spv_binary_(spv_binary),
       fail_stream_(&success_, &errors_),
@@ -76,11 +75,6 @@
 ParserImpl::~ParserImpl() = default;
 
 bool ParserImpl::Parse() {
-  if (ctx_.type_mgr == nullptr) {
-    Fail() << "Missing type manager";
-    return false;
-  }
-
   if (!success_) {
     return false;
   }
@@ -134,18 +128,18 @@
 
   switch (spirv_type->kind()) {
     case spvtools::opt::analysis::Type::kVoid:
-      result = ctx_.type_mgr->Get(std::make_unique<ast::type::VoidType>());
+      result = ctx_.type_mgr().Get(std::make_unique<ast::type::VoidType>());
       break;
     case spvtools::opt::analysis::Type::kBool:
-      result = ctx_.type_mgr->Get(std::make_unique<ast::type::BoolType>());
+      result = ctx_.type_mgr().Get(std::make_unique<ast::type::BoolType>());
       break;
     case spvtools::opt::analysis::Type::kInteger: {
       const auto* int_ty = spirv_type->AsInteger();
       if (int_ty->width() == 32) {
         if (int_ty->IsSigned()) {
-          result = ctx_.type_mgr->Get(std::make_unique<ast::type::I32Type>());
+          result = ctx_.type_mgr().Get(std::make_unique<ast::type::I32Type>());
         } else {
-          result = ctx_.type_mgr->Get(std::make_unique<ast::type::U32Type>());
+          result = ctx_.type_mgr().Get(std::make_unique<ast::type::U32Type>());
         }
       } else {
         Fail() << "unhandled integer width: " << int_ty->width();
@@ -155,7 +149,7 @@
     case spvtools::opt::analysis::Type::kFloat: {
       const auto* float_ty = spirv_type->AsFloat();
       if (float_ty->width() == 32) {
-        result = ctx_.type_mgr->Get(std::make_unique<ast::type::F32Type>());
+        result = ctx_.type_mgr().Get(std::make_unique<ast::type::F32Type>());
       } else {
         Fail() << "unhandled float width: " << float_ty->width();
       }
@@ -166,7 +160,7 @@
       const auto num_elem = vec_ty->element_count();
       auto* ast_elem_ty = ConvertType(type_mgr_->GetId(vec_ty->element_type()));
       if (ast_elem_ty != nullptr) {
-        result = ctx_.type_mgr->Get(
+        result = ctx_.type_mgr().Get(
             std::make_unique<ast::type::VectorType>(ast_elem_ty, num_elem));
       }
       // In the error case, we'll already have emitted a diagnostic.
@@ -180,7 +174,7 @@
       const auto num_columns = mat_ty->element_count();
       auto* ast_scalar_ty = ConvertType(type_mgr_->GetId(scalar_ty));
       if (ast_scalar_ty != nullptr) {
-        result = ctx_.type_mgr->Get(std::make_unique<ast::type::MatrixType>(
+        result = ctx_.type_mgr().Get(std::make_unique<ast::type::MatrixType>(
             ast_scalar_ty, num_rows, num_columns));
       }
       // In the error case, we'll already have emitted a diagnostic.
diff --git a/src/reader/spirv/parser_impl.h b/src/reader/spirv/parser_impl.h
index d7487c5..a422cb6 100644
--- a/src/reader/spirv/parser_impl.h
+++ b/src/reader/spirv/parser_impl.h
@@ -45,9 +45,9 @@
 class ParserImpl : Reader {
  public:
   /// Creates a new parser
-  /// @param ctx the context object
+  /// @param ctx the non-null context object
   /// @param input the input data to parse
-  ParserImpl(const Context& ctx, const std::vector<uint32_t>& input);
+  ParserImpl(Context* ctx, const std::vector<uint32_t>& input);
   /// Destructor
   ~ParserImpl() override;
 
diff --git a/src/reader/spirv/parser_impl_test_helper.h b/src/reader/spirv/parser_impl_test_helper.h
index 0838b00..97ac096 100644
--- a/src/reader/spirv/parser_impl_test_helper.h
+++ b/src/reader/spirv/parser_impl_test_helper.h
@@ -34,26 +34,24 @@
   ~SpvParserTest() = default;
 
   /// Sets up the test helper
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   /// Tears down the test helper
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   /// Retrieves the parser from the helper
   /// @param input the string to parse
   /// @returns the parser implementation
   ParserImpl* parser(const std::vector<uint32_t>& input) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, input);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, input);
     return impl_.get();
   }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 
 }  // namespace spirv
diff --git a/src/reader/spirv/parser_test.cc b/src/reader/spirv/parser_test.cc
index a893905..bef23df 100644
--- a/src/reader/spirv/parser_test.cc
+++ b/src/reader/spirv/parser_test.cc
@@ -30,7 +30,7 @@
 TEST_F(ParserTest, Uint32VecEmpty) {
   std::vector<uint32_t> data;
   Context ctx;
-  Parser p(ctx, data);
+  Parser p(&ctx, data);
   EXPECT_FALSE(p.Parse());
   // TODO(dneto): What message?
 }
diff --git a/src/reader/wgsl/parser.cc b/src/reader/wgsl/parser.cc
index 597d578..2b2adc7 100644
--- a/src/reader/wgsl/parser.cc
+++ b/src/reader/wgsl/parser.cc
@@ -20,7 +20,7 @@
 namespace reader {
 namespace wgsl {
 
-Parser::Parser(const Context& ctx, const std::string& input)
+Parser::Parser(Context* ctx, const std::string& input)
     : Reader(ctx), impl_(std::make_unique<ParserImpl>(ctx, input)) {}
 
 Parser::~Parser() = default;
diff --git a/src/reader/wgsl/parser.h b/src/reader/wgsl/parser.h
index aa511e8..6fe3390 100644
--- a/src/reader/wgsl/parser.h
+++ b/src/reader/wgsl/parser.h
@@ -30,9 +30,9 @@
 class Parser : public Reader {
  public:
   /// Creates a new parser
-  /// @param ctx the context object
+  /// @param ctx the non-null context object
   /// @param input the input string to parse
-  Parser(const Context& ctx, const std::string& input);
+  Parser(Context* ctx, const std::string& input);
   ~Parser() override;
 
   /// Run the parser
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index e2db44d..f2131f5 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -71,8 +71,8 @@
 namespace reader {
 namespace wgsl {
 
-ParserImpl::ParserImpl(const Context& ctx, const std::string& input)
-    : ctx_(ctx), lexer_(std::make_unique<Lexer>(input)) {}
+ParserImpl::ParserImpl(Context* ctx, const std::string& input)
+    : ctx_(*ctx), lexer_(std::make_unique<Lexer>(input)) {}
 
 ParserImpl::~ParserImpl() = default;
 
@@ -134,11 +134,6 @@
 }
 
 bool ParserImpl::Parse() {
-  if (ctx_.type_mgr == nullptr) {
-    set_error(peek(), "missing type manager");
-    return false;
-  }
-
   translation_unit();
   return !has_error();
 }
@@ -690,7 +685,7 @@
     }
 
     str->set_name(name);
-    type = ctx_.type_mgr->Get(std::move(str));
+    type = ctx_.type_mgr().Get(std::move(str));
   }
   if (type == nullptr) {
     set_error(peek(), "invalid type for alias");
@@ -698,7 +693,7 @@
   }
 
   auto alias =
-      ctx_.type_mgr->Get(std::make_unique<ast::type::AliasType>(name, type));
+      ctx_.type_mgr().Get(std::make_unique<ast::type::AliasType>(name, type));
   register_alias(name, alias);
 
   return alias->AsAlias();
@@ -738,19 +733,19 @@
   }
   if (t.IsBool()) {
     next();  // Consume the peek
-    return ctx_.type_mgr->Get(std::make_unique<ast::type::BoolType>());
+    return ctx_.type_mgr().Get(std::make_unique<ast::type::BoolType>());
   }
   if (t.IsF32()) {
     next();  // Consume the peek
-    return ctx_.type_mgr->Get(std::make_unique<ast::type::F32Type>());
+    return ctx_.type_mgr().Get(std::make_unique<ast::type::F32Type>());
   }
   if (t.IsI32()) {
     next();  // Consume the peek
-    return ctx_.type_mgr->Get(std::make_unique<ast::type::I32Type>());
+    return ctx_.type_mgr().Get(std::make_unique<ast::type::I32Type>());
   }
   if (t.IsU32()) {
     next();  // Consume the peek
-    return ctx_.type_mgr->Get(std::make_unique<ast::type::U32Type>());
+    return ctx_.type_mgr().Get(std::make_unique<ast::type::U32Type>());
   }
   if (t.IsVec2() || t.IsVec3() || t.IsVec4()) {
     return type_decl_vector(t);
@@ -806,7 +801,7 @@
     return nullptr;
   }
 
-  return ctx_.type_mgr->Get(
+  return ctx_.type_mgr().Get(
       std::make_unique<ast::type::PointerType>(subtype, sc));
 }
 
@@ -839,7 +834,7 @@
     return nullptr;
   }
 
-  return ctx_.type_mgr->Get(
+  return ctx_.type_mgr().Get(
       std::make_unique<ast::type::VectorType>(subtype, count));
 }
 
@@ -880,7 +875,7 @@
     return nullptr;
   }
 
-  return ctx_.type_mgr->Get(
+  return ctx_.type_mgr().Get(
       std::make_unique<ast::type::ArrayType>(subtype, size));
 }
 
@@ -920,7 +915,7 @@
     return nullptr;
   }
 
-  return ctx_.type_mgr->Get(
+  return ctx_.type_mgr().Get(
       std::make_unique<ast::type::MatrixType>(subtype, rows, columns));
 }
 
@@ -1214,7 +1209,7 @@
   auto t = peek();
   if (t.IsVoid()) {
     next();  // Consume the peek
-    return ctx_.type_mgr->Get(std::make_unique<ast::type::VoidType>());
+    return ctx_.type_mgr().Get(std::make_unique<ast::type::VoidType>());
   }
   return type_decl();
 }
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h
index 5413d85..6c8e813 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -57,9 +57,9 @@
 class ParserImpl {
  public:
   /// Creates a new parser
-  /// @param ctx the context object
+  /// @param ctx the non-null context object
   /// @param input the input string to parse
-  ParserImpl(const Context& ctx, const std::string& input);
+  ParserImpl(Context* ctx, const std::string& input);
   ~ParserImpl();
 
   /// Run the parser
@@ -351,7 +351,7 @@
   ast::type::Type* type_decl_array(Token t);
   ast::type::Type* type_decl_matrix(Token t);
 
-  const Context& ctx_;
+  Context& ctx_;
   std::string error_;
   std::unique_ptr<Lexer> lexer_;
   std::deque<Token> token_queue_;
diff --git a/src/reader/wgsl/parser_impl_builtin_decoration_test.cc b/src/reader/wgsl/parser_impl_builtin_decoration_test.cc
index d33b6d6..09755b6 100644
--- a/src/reader/wgsl/parser_impl_builtin_decoration_test.cc
+++ b/src/reader/wgsl/parser_impl_builtin_decoration_test.cc
@@ -36,22 +36,20 @@
   BuiltinTest() = default;
   ~BuiltinTest() = default;
 
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, str);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
     return impl_.get();
   }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 
 TEST_P(BuiltinTest, Parses) {
diff --git a/src/reader/wgsl/parser_impl_derivative_modifier_test.cc b/src/reader/wgsl/parser_impl_derivative_modifier_test.cc
index 6c84dd5..b73469a 100644
--- a/src/reader/wgsl/parser_impl_derivative_modifier_test.cc
+++ b/src/reader/wgsl/parser_impl_derivative_modifier_test.cc
@@ -38,22 +38,20 @@
   DerivativeModifierTest() = default;
   ~DerivativeModifierTest() = default;
 
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, str);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
     return impl_.get();
   }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 
 TEST_P(DerivativeModifierTest, Parses) {
diff --git a/src/reader/wgsl/parser_impl_pipeline_stage_test.cc b/src/reader/wgsl/parser_impl_pipeline_stage_test.cc
index d36cb0a..f280575 100644
--- a/src/reader/wgsl/parser_impl_pipeline_stage_test.cc
+++ b/src/reader/wgsl/parser_impl_pipeline_stage_test.cc
@@ -36,22 +36,20 @@
   PipelineStageTest() = default;
   ~PipelineStageTest() = default;
 
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, str);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
     return impl_.get();
   }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 
 TEST_P(PipelineStageTest, Parses) {
diff --git a/src/reader/wgsl/parser_impl_storage_class_test.cc b/src/reader/wgsl/parser_impl_storage_class_test.cc
index 986b8ab..7c27682 100644
--- a/src/reader/wgsl/parser_impl_storage_class_test.cc
+++ b/src/reader/wgsl/parser_impl_storage_class_test.cc
@@ -36,22 +36,20 @@
   StorageClassTest() = default;
   ~StorageClassTest() = default;
 
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, str);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
     return impl_.get();
   }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 
 TEST_P(StorageClassTest, Parses) {
diff --git a/src/reader/wgsl/parser_impl_struct_decoration_test.cc b/src/reader/wgsl/parser_impl_struct_decoration_test.cc
index ae2ff1c..d32e2ab 100644
--- a/src/reader/wgsl/parser_impl_struct_decoration_test.cc
+++ b/src/reader/wgsl/parser_impl_struct_decoration_test.cc
@@ -37,22 +37,20 @@
   StructDecorationTest() = default;
   ~StructDecorationTest() = default;
 
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, str);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
     return impl_.get();
   }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 
 TEST_P(StructDecorationTest, Parses) {
diff --git a/src/reader/wgsl/parser_impl_test_helper.h b/src/reader/wgsl/parser_impl_test_helper.h
index 63f50cb..a58b32f 100644
--- a/src/reader/wgsl/parser_impl_test_helper.h
+++ b/src/reader/wgsl/parser_impl_test_helper.h
@@ -34,29 +34,27 @@
   ~ParserImplTest() = default;
 
   /// Sets up the test helper
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   /// Tears down the test helper
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   /// Retrieves the parser from the helper
   /// @param str the string to parse
   /// @returns the parser implementation
   ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, str);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
     return impl_.get();
   }
 
   /// @returns the type manager
-  TypeManager* tm() { return &tm_; }
+  TypeManager* tm() { return &(ctx_.type_mgr()); }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 
 }  // namespace wgsl
diff --git a/src/reader/wgsl/parser_impl_type_decl_test.cc b/src/reader/wgsl/parser_impl_type_decl_test.cc
index 13a4657..df8b65f 100644
--- a/src/reader/wgsl/parser_impl_type_decl_test.cc
+++ b/src/reader/wgsl/parser_impl_type_decl_test.cc
@@ -125,22 +125,20 @@
   VecTest() = default;
   ~VecTest() = default;
 
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, str);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
     return impl_.get();
   }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 
 TEST_P(VecTest, Parse) {
@@ -163,22 +161,20 @@
   VecMissingGreaterThanTest() = default;
   ~VecMissingGreaterThanTest() = default;
 
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, str);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
     return impl_.get();
   }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 
 TEST_P(VecMissingGreaterThanTest, Handles_Missing_GreaterThan) {
@@ -200,22 +196,20 @@
   VecMissingLessThanTest() = default;
   ~VecMissingLessThanTest() = default;
 
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, str);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
     return impl_.get();
   }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 
 TEST_P(VecMissingLessThanTest, Handles_Missing_GreaterThan) {
@@ -237,22 +231,20 @@
   VecBadType() = default;
   ~VecBadType() = default;
 
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, str);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
     return impl_.get();
   }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 
 TEST_P(VecBadType, Handles_Unknown_Type) {
@@ -274,22 +266,20 @@
   VecMissingType() = default;
   ~VecMissingType() = default;
 
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, str);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
     return impl_.get();
   }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 
 TEST_P(VecMissingType, Handles_Missing_Type) {
@@ -493,22 +483,20 @@
   MatrixTest() = default;
   ~MatrixTest() = default;
 
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, str);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
     return impl_.get();
   }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 
 TEST_P(MatrixTest, Parse) {
@@ -539,22 +527,20 @@
   MatrixMissingGreaterThanTest() = default;
   ~MatrixMissingGreaterThanTest() = default;
 
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, str);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
     return impl_.get();
   }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 TEST_P(MatrixMissingGreaterThanTest, Handles_Missing_GreaterThan) {
   auto params = GetParam();
@@ -581,22 +567,20 @@
   MatrixMissingLessThanTest() = default;
   ~MatrixMissingLessThanTest() = default;
 
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, str);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
     return impl_.get();
   }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 TEST_P(MatrixMissingLessThanTest, Handles_Missing_GreaterThan) {
   auto params = GetParam();
@@ -623,22 +607,20 @@
   MatrixBadType() = default;
   ~MatrixBadType() = default;
 
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, str);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
     return impl_.get();
   }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 TEST_P(MatrixBadType, Handles_Unknown_Type) {
   auto params = GetParam();
@@ -665,22 +647,20 @@
   MatrixMissingType() = default;
   ~MatrixMissingType() = default;
 
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, str);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
     return impl_.get();
   }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 TEST_P(MatrixMissingType, Handles_Missing_Type) {
   auto params = GetParam();
diff --git a/src/reader/wgsl/parser_impl_variable_storage_decoration_test.cc b/src/reader/wgsl/parser_impl_variable_storage_decoration_test.cc
index e82a44d..9bf38aa 100644
--- a/src/reader/wgsl/parser_impl_variable_storage_decoration_test.cc
+++ b/src/reader/wgsl/parser_impl_variable_storage_decoration_test.cc
@@ -36,22 +36,20 @@
   VariableStorageTest() = default;
   ~VariableStorageTest() = default;
 
-  void SetUp() { ctx_.type_mgr = &tm_; }
+  void SetUp() { ctx_.Reset(); }
 
   void TearDown() {
     impl_ = nullptr;
-    ctx_.type_mgr = nullptr;
   }
 
   ParserImpl* parser(const std::string& str) {
-    impl_ = std::make_unique<ParserImpl>(ctx_, str);
+    impl_ = std::make_unique<ParserImpl>(&ctx_, str);
     return impl_.get();
   }
 
  private:
   std::unique_ptr<ParserImpl> impl_;
   Context ctx_;
-  TypeManager tm_;
 };
 
 TEST_P(VariableStorageTest, Parses) {
diff --git a/src/reader/wgsl/parser_test.cc b/src/reader/wgsl/parser_test.cc
index 1d93720..fa06290 100644
--- a/src/reader/wgsl/parser_test.cc
+++ b/src/reader/wgsl/parser_test.cc
@@ -25,19 +25,15 @@
 using ParserTest = testing::Test;
 
 TEST_F(ParserTest, Empty) {
-  TypeManager tm;
   Context ctx;
-  ctx.type_mgr = &tm;
-  Parser p(ctx, "");
+  Parser p(&ctx, "");
   ASSERT_TRUE(p.Parse()) << p.error();
 }
 
 TEST_F(ParserTest, DISABLED_Parses) {
-  TypeManager tm;
   Context ctx;
-  ctx.type_mgr = &tm;
 
-  Parser p(ctx, R"(
+  Parser p(&ctx, R"(
 import "GLSL.std.430" as glsl;
 
 [[location 0]] var<out> gl_FragColor : vec4<f32>;
@@ -56,7 +52,7 @@
 
 TEST_F(ParserTest, DISABLED_HandlesError) {
   Context ctx;
-  Parser p(ctx, R"(
+  Parser p(&ctx, R"(
 import "GLSL.std.430" as glsl;
 
 fn main() ->  {  # missing return type
diff --git a/src/type_manager.cc b/src/type_manager.cc
index e52c3ff..88569ce 100644
--- a/src/type_manager.cc
+++ b/src/type_manager.cc
@@ -22,6 +22,10 @@
 
 TypeManager::~TypeManager() = default;
 
+void TypeManager::Reset() {
+  types_.clear();
+}
+
 ast::type::Type* TypeManager::Get(std::unique_ptr<ast::type::Type> type) {
   auto name = type->type_name();
 
diff --git a/src/type_manager.h b/src/type_manager.h
index 61ca864..eb26a25 100644
--- a/src/type_manager.h
+++ b/src/type_manager.h
@@ -29,11 +29,21 @@
   TypeManager();
   ~TypeManager();
 
+  /// Clears all registered types.
+  void Reset();
+
   /// Get the given type from the type manager
   /// @param type The type to register
   /// @return the pointer to the registered type
   ast::type::Type* Get(std::unique_ptr<ast::type::Type> type);
 
+  /// Returns the type map, for testing purposes.
+  /// @returns the mapping from name string to type.
+  const std::unordered_map<std::string, std::unique_ptr<ast::type::Type>>&
+  TypesForTesting() {
+    return types_;
+  }
+
  private:
   std::unordered_map<std::string, std::unique_ptr<ast::type::Type>> types_;
 };
diff --git a/src/type_manager_test.cc b/src/type_manager_test.cc
index 004450f..a0526d1 100644
--- a/src/type_manager_test.cc
+++ b/src/type_manager_test.cc
@@ -52,5 +52,18 @@
   EXPECT_TRUE(t2->IsU32());
 }
 
+TEST_F(TypeManagerTest, ResetClearsPreviousData) {
+  TypeManager tm;
+  auto t = tm.Get(std::make_unique<ast::type::I32Type>());
+  ASSERT_NE(t, nullptr);
+
+  EXPECT_FALSE(tm.TypesForTesting().empty());
+  tm.Reset();
+  EXPECT_TRUE(tm.TypesForTesting().empty());
+
+  auto t2 = tm.Get(std::make_unique<ast::type::I32Type>());
+  ASSERT_NE(t2, nullptr);
+}
+
 }  // namespace
 }  // namespace tint