Index: src/Common/GC.cc
===================================================================
--- src/Common/GC.cc	(revision 68f9c43ecf1873cbb5f06aee682704b56612ed16)
+++ src/Common/GC.cc	(revision 68f9c43ecf1873cbb5f06aee682704b56612ed16)
@@ -0,0 +1,111 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// GC.cc --
+//
+// Author           : Aaron B. Moss
+// Created On       : Thu Mar 15 14:47:00 2018
+// Last Modified By : Aaron B. Moss
+// Last Modified On : Thu Mar 15 14:47:00 2018
+// Update Count     : 1
+//
+
+#include "GC.h"
+
+#include <algorithm>
+
+GC& GC::get() {
+	static GC gc;
+	return gc;
+}
+
+GC::GC() : mark(false), old(), young(), using_young(false) {
+	old.reserve(70000);
+}
+
+GC::~GC() {
+	for ( GC_Object* o : young ) {
+		delete o;
+	}
+
+	for ( GC_Object* o : old ) {
+		delete o;
+	}
+}
+
+const GC& GC::operator<< (const GC_Traceable* obj) const {
+	if( obj )
+	{
+		bool isMarked = obj->mark == this->mark;
+		if( !isMarked ) {
+			obj->mark = this->mark;
+			obj->trace( *this );
+		}
+	}
+	return *this;
+}
+
+void GC::register_object(GC_Object* obj) {
+	(using_young ? young : old).push_back(obj);
+	obj->mark = this->mark;
+}
+
+void GC::new_generation() {
+	using_young = true;
+}
+
+void GC::collect_young() {
+	// check young generation, just reset mark if not using
+	if ( ! using_young ) {
+		mark = !mark;
+		return;
+	}
+
+	// collect young gen
+	for ( GC_Object*& obj : young ) {
+		if ( obj->mark != mark ) {
+			delete obj;
+			obj = nullptr;
+		}
+	}
+	
+	// move uncollected elements into old gen
+	auto end_live = std::remove( young.begin(), young.end(), nullptr );
+	old.insert( old.end(), young.begin(), end_live );
+	
+	// clear young gen
+	using_young = false;
+	young.clear();
+
+	// reset mark for next collection
+	mark = !mark;
+}
+
+void GC::collect() {
+	// collect old gen
+	for ( GC_Object*& obj : old ) {
+		if ( obj->mark != mark ) {
+			delete obj;
+			obj = nullptr;
+		}
+	}
+
+	// clear collected elements
+	old.erase( std::remove( old.begin(), old.end(), nullptr ), old.end() );
+
+	// collect young gen (also resets mark)
+	collect_young();
+}
+
+GC_Object::GC_Object() {
+	GC::get().register_object( this );
+}
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Common/GC.h
===================================================================
--- src/Common/GC.h	(revision 68f9c43ecf1873cbb5f06aee682704b56612ed16)
+++ src/Common/GC.h	(revision 68f9c43ecf1873cbb5f06aee682704b56612ed16)
@@ -0,0 +1,117 @@
+//
+// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
+//
+// The contents of this file are covered under the licence agreement in the
+// file "LICENCE" distributed with Cforall.
+//
+// GC.h --
+//
+// Author           : Aaron B. Moss
+// Created On       : Thu Mar 15 14:47:00 2018
+// Last Modified By : Aaron B. Moss
+// Last Modified On : Thu Mar 15 14:47:00 2018
+// Update Count     : 1
+//
+
+#pragma once
+
+#include <vector>
+
+class GC_Traceable;
+class GC_Object;
+
+/// Manually traced and called garbage collector
+class GC {
+	friend class GcTracer;
+public:
+	/// Gets singleton GC instance
+	static GC& get();
+
+	/// Traces a traceable object
+	const GC& operator<< (const GC_Traceable*) const;
+
+	/// Adds a new object to garbage collection
+	void register_object(GC_Object*);
+
+	/// Use young generation for subsequent new objects
+	void new_generation();
+
+	/// Collects the young generation, placing survivors in old generation.
+	/// Old generation is used for subsequent new objects.
+	void collect_young();
+
+	/// Collects all memory; use old generation afterward.
+	void collect();
+
+	/// Collects all contained objects
+	~GC();
+
+private:
+	GC();
+
+	/// The current collection's mark bit
+	bool mark;
+
+	typedef std::vector<class GC_Object*> Generation;
+	Generation old;
+	Generation young;
+	bool using_young;
+};
+
+/// Use young generation until next collection
+inline void new_generation() { GC::get().new_generation(); }
+
+/// no-op default trace
+template<typename T>
+inline const GC& operator<< (const GC& gc, const T& x) { return gc; }
+
+inline void traceAll(const GC& gc) {}
+
+/// Marks all arguments as live in current generation
+template<typename T, typename... Args>
+inline void traceAll(const GC& gc, T& x, Args&... xs) {
+	gc << x;
+	traceAll(gc, xs...);
+}
+
+/// Traces young-generation roots and does a young collection
+template<typename... Args>
+inline void collect_young(Args&... roots) {
+	GC& gc = GC::get();
+	traceAll(gc, roots...);
+	gc.collect_young();
+}
+
+/// Traces roots and collects other elements
+template<typename... Args>
+inline void collect(Args&... roots) {
+	GC& gc = GC::get();
+	traceAll(gc, roots...);
+	gc.collect();
+}
+
+/// Class that is traced by the GC, but not managed by it
+class GC_Traceable {
+	friend class GC;
+	friend class GcTracer;
+
+	mutable bool mark;
+protected:
+	/// override to trace any child objects
+	virtual void trace(const GC& gc) const {}
+};
+
+/// Class that is managed by the GC
+class GC_Object : public GC_Traceable {
+	friend class GC;
+protected:
+	virtual ~GC_Object() {}
+public:
+	GC_Object();
+};
+
+// Local Variables: //
+// tab-width: 4 //
+// mode: c++ //
+// compile-command: "make install" //
+// End: //
Index: src/Common/PassVisitor.h
===================================================================
--- src/Common/PassVisitor.h	(revision 1feb535fb19cf9656f8f85cf2ef61a8985f3bf97)
+++ src/Common/PassVisitor.h	(revision 68f9c43ecf1873cbb5f06aee682704b56612ed16)
@@ -152,4 +152,6 @@
 	virtual void visit( Attribute * attribute ) override final;
 
+	virtual void visit( TypeSubstitution * sub ) final;
+
 	virtual DeclarationWithType * mutate( ObjectDecl * objectDecl ) override final;
 	virtual DeclarationWithType * mutate( FunctionDecl * functionDecl ) override final;
Index: src/Common/PassVisitor.impl.h
===================================================================
--- src/Common/PassVisitor.impl.h	(revision 1feb535fb19cf9656f8f85cf2ef61a8985f3bf97)
+++ src/Common/PassVisitor.impl.h	(revision 68f9c43ecf1873cbb5f06aee682704b56612ed16)
@@ -2556,4 +2556,18 @@
 // TypeSubstitution
 template< typename pass_type >
+void PassVisitor< pass_type >::visit( TypeSubstitution * node ) {
+	VISIT_START( node );
+
+	for ( auto & p : node->typeEnv ) {
+		indexerScopedAccept( p.second, *this );
+	}
+	for ( auto & p : node->varEnv ) {
+		indexerScopedAccept( p.second, *this );
+	}
+
+	VISIT_END( node );
+}
+
+template< typename pass_type >
 TypeSubstitution * PassVisitor< pass_type >::mutate( TypeSubstitution * node ) {
 	MUTATE_START( node );
Index: src/Common/module.mk
===================================================================
--- src/Common/module.mk	(revision 1feb535fb19cf9656f8f85cf2ef61a8985f3bf97)
+++ src/Common/module.mk	(revision 68f9c43ecf1873cbb5f06aee682704b56612ed16)
@@ -18,3 +18,4 @@
        Common/UniqueName.cc \
        Common/DebugMalloc.cc \
+       Common/GC.cc \
        Common/Assert.cc
Index: src/Common/utility.h
===================================================================
--- src/Common/utility.h	(revision 1feb535fb19cf9656f8f85cf2ef61a8985f3bf97)
+++ src/Common/utility.h	(revision 68f9c43ecf1873cbb5f06aee682704b56612ed16)
@@ -190,12 +190,9 @@
 
 template <typename E, typename UnaryPredicate, template< typename, typename...> class Container, typename... Args >
-void filter( Container< E *, Args... > & container, UnaryPredicate pred, bool doDelete ) {
+void filter( Container< E *, Args... > & container, UnaryPredicate pred ) {
 	auto i = begin( container );
 	while ( i != end( container ) ) {
 		auto it = next( i );
 		if ( pred( *i ) ) {
-			if ( doDelete ) {
-				delete *i;
-			} // if
 			container.erase( i );
 		} // if
