Index: src/ResolvExpr/AdjustExprType.cc
===================================================================
--- src/ResolvExpr/AdjustExprType.cc	(revision a8706fc00f87d52e8a2088039ea7e9d0d0ba8b7c)
+++ src/ResolvExpr/AdjustExprType.cc	(revision eba74ba03a2c29999def828ffaf6afc87e2b40d1)
@@ -66,12 +66,9 @@
 
 	Type * AdjustExprType::postmutate( ArrayType * arrayType ) {
-		PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base );
-		arrayType->base = nullptr;
-		delete arrayType;
-		return pointerType;
+		return new PointerType{ arrayType->get_qualifiers(), arrayType->base };
 	}
 
 	Type * AdjustExprType::postmutate( FunctionType * functionType ) {
-		return new PointerType( Type::Qualifiers(), functionType );
+		return new PointerType{ Type::Qualifiers(), functionType };
 	}
 
@@ -80,12 +77,10 @@
 		if ( env.lookup( typeInst->get_name(), eqvClass ) ) {
 			if ( eqvClass.data.kind == TypeDecl::Ftype ) {
-				PointerType *pointerType = new PointerType( Type::Qualifiers(), typeInst );
-				return pointerType;
+				return new PointerType{ Type::Qualifiers(), typeInst };
 			}
 		} else if ( NamedTypeDecl *ntDecl = indexer.lookupType( typeInst->get_name() ) ) {
 			if ( TypeDecl *tyDecl = dynamic_cast< TypeDecl* >( ntDecl ) ) {
 				if ( tyDecl->get_kind() == TypeDecl::Ftype ) {
-					PointerType *pointerType = new PointerType( Type::Qualifiers(), typeInst );
-					return pointerType;
+					return new PointerType{ Type::Qualifiers(), typeInst };
 				} // if
 			} // if
Index: src/ResolvExpr/Alternative.cc
===================================================================
--- src/ResolvExpr/Alternative.cc	(revision a8706fc00f87d52e8a2088039ea7e9d0d0ba8b7c)
+++ src/ResolvExpr/Alternative.cc	(revision eba74ba03a2c29999def828ffaf6afc87e2b40d1)
@@ -20,8 +20,11 @@
 #include <utility>                       // for move
 
+#include "Common/GC.h"
+#include "Common/PassVisitor.h"
 #include "Common/utility.h"              // for maybeClone
 #include "ResolvExpr/Cost.h"             // for Cost, Cost::zero, operator<<
 #include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
 #include "SynTree/Expression.h"          // for Expression
+#include "SynTree/GcTracer.h"
 #include "SynTree/Type.h"                // for Type
 
@@ -34,35 +37,15 @@
 	Alternative::Alternative( Expression *expr, const TypeEnvironment &env, const Cost& cost, const Cost &cvtCost )
 		: cost( cost ), cvtCost( cvtCost ), expr( expr ), env( env ) {}
-
-	Alternative::Alternative( const Alternative &other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( maybeClone( other.expr ) ), env( other.env ) {
-	}
-
-	Alternative &Alternative::operator=( const Alternative &other ) {
-		if ( &other == this ) return *this;
-		delete expr;
-		cost = other.cost;
-		cvtCost = other.cvtCost;
-		expr = maybeClone( other.expr );
-		env = other.env;
+	
+	Alternative::Alternative( const Alternative& o )
+		: cost( o.cost ), cvtCost( o.cvtCost ), expr( maybeClone( o.expr ) ), env( o.env ) {}
+	
+	Alternative & Alternative::operator= ( const Alternative& o ) {
+		if ( &o == this ) return *this;
+		cost = o.cost;
+		cvtCost = o.cvtCost;
+		expr = maybeClone( o.expr );
+		env = o.env;
 		return *this;
-	}
-
-	Alternative::Alternative( Alternative && other ) : cost( other.cost ), cvtCost( other.cvtCost ), expr( other.expr ), env( other.env ) {
-		other.expr = nullptr;
-	}
-
-	Alternative & Alternative::operator=( Alternative && other ) {
-		if ( &other == this )  return *this;
-		delete expr;
-		cost = other.cost;
-		cvtCost = other.cvtCost;
-		expr = other.expr;
-		env = other.env;
-		other.expr = nullptr;
-		return *this;
-	}
-
-	Alternative::~Alternative() {
-		delete expr;
 	}
 
@@ -96,4 +79,11 @@
 	}
 
+	const GC& operator<< ( const GC& gc, const Alternative& alt ) {
+		PassVisitor<GcTracer> tracer{ gc };
+		maybeAccept( alt.expr, tracer );
+		tracer << alt.env;
+		return gc;
+	}
+
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/Alternative.h
===================================================================
--- src/ResolvExpr/Alternative.h	(revision a8706fc00f87d52e8a2088039ea7e9d0d0ba8b7c)
+++ src/ResolvExpr/Alternative.h	(revision eba74ba03a2c29999def828ffaf6afc87e2b40d1)
@@ -24,4 +24,6 @@
 class Expression;
 
+class GC;
+
 namespace ResolvExpr {
 	struct Alternative {
@@ -30,21 +32,13 @@
 		Alternative( Expression *expr, const TypeEnvironment &env, const Cost &cost, const Cost &cvtCost );
 		Alternative( const Alternative &other );
-		Alternative &operator=( const Alternative &other );
-		Alternative( Alternative && other );
-		Alternative &operator=( Alternative && other );
-		~Alternative();
+		Alternative & operator= ( const Alternative &other );
+		Alternative( Alternative&& other ) = default;
+		Alternative & operator= ( Alternative&& other ) = default;
 
 		void print( std::ostream &os, Indenter indent = {} ) const;
 
-		/// Returns the stored expression, but released from management of this Alternative
-		Expression* release_expr() {
-			Expression* tmp = expr;
-			expr = nullptr;
-			return tmp;
-		}
-
 		Cost cost;
 		Cost cvtCost;
-		Expression *expr;
+		Expression * expr;
 		TypeEnvironment env;
 	};
@@ -62,4 +56,6 @@
 		return os;
 	}
+
+	const GC& operator<< ( const GC&, const Alternative& );
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision a8706fc00f87d52e8a2088039ea7e9d0d0ba8b7c)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision eba74ba03a2c29999def828ffaf6afc87e2b40d1)
@@ -21,5 +21,5 @@
 #include <list>                    // for _List_iterator, list, _List_const_...
 #include <map>                     // for _Rb_tree_iterator, map, _Rb_tree_c...
-#include <memory>                  // for allocator_traits<>::value_type, unique_ptr
+#include <memory>                  // for allocator_traits<>::value_type
 #include <utility>                 // for pair
 #include <vector>                  // for vector
@@ -35,4 +35,5 @@
 #include "ResolveTypeof.h"         // for resolveTypeof
 #include "Resolver.h"              // for resolveStmtExpr
+#include "Common/GC.h"             // for new_static_root
 #include "SymTab/Indexer.h"        // for Indexer
 #include "SymTab/Mangler.h"        // for Mangler
@@ -101,5 +102,5 @@
 		void addAnonConversions( const Alternative & alt );
 		/// Adds alternatives for member expressions, given the aggregate, conversion cost for that aggregate, and name of the member
-		template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
+		template< typename StructOrUnionType > void addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name );
 		/// Adds alternatives for member expressions where the left side has tuple type
 		void addTupleMembers( TupleType * tupleType, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member );
@@ -165,5 +166,4 @@
 					candidate->env.apply( newType );
 					mangleName = SymTab::Mangler::mangle( newType );
-					delete newType;
 				}
 				std::map< std::string, PruneStruct >::iterator mapPlace = selected.find( mangleName );
@@ -297,27 +297,21 @@
 		// adds anonymous member interpretations whenever an aggregate value type is seen.
 		// it's okay for the aggregate expression to have reference type -- cast it to the base type to treat the aggregate as the referenced value
-		std::unique_ptr<Expression> aggrExpr( alt.expr->clone() );
+		Expression* aggrExpr = alt.expr->clone();
 		alt.env.apply( aggrExpr->get_result() );
 		Type * aggrType = aggrExpr->get_result();
 		if ( dynamic_cast< ReferenceType * >( aggrType ) ) {
 			aggrType = aggrType->stripReferences();
-			aggrExpr.reset( new CastExpr( aggrExpr.release(), aggrType->clone() ) );
+			aggrExpr = new CastExpr{ aggrExpr, aggrType->clone() };
 		}
 
 		if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
-			NameExpr nameExpr( "" );
-			addAggMembers( structInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr );
+			addAggMembers( structInst, aggrExpr, alt.cost+Cost::safe, alt.env, "" );
 		} else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
-			NameExpr nameExpr( "" );
-			addAggMembers( unionInst, aggrExpr.get(), alt.cost+Cost::safe, alt.env, &nameExpr );
+			addAggMembers( unionInst, aggrExpr, alt.cost+Cost::safe, alt.env, "" );
 		} // if
 	}
 
 	template< typename StructOrUnionType >
-	void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
-		// by this point, member must be a name expr
-		NameExpr * nameExpr = dynamic_cast< NameExpr * >( member );
-		if ( ! nameExpr ) return;
-		const std::string & name = nameExpr->get_name();
+	void AlternativeFinder::Finder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, const std::string & name ) {
 		std::list< Declaration* > members;
 		aggInst->lookup( name, members );
@@ -568,5 +562,4 @@
 
 				Expression *varExpr = data.combine( newerAlt.cvtCost );
-				delete varExpr->get_result();
 				varExpr->set_result( adjType->clone() );
 				PRINT(
@@ -585,6 +578,4 @@
 				(*inferParameters)[ curDecl->get_uniqueId() ] = ParamEntry( candidate->get_uniqueId(), adjType->clone(), curDecl->get_type()->clone(), varExpr );
 				inferRecursive( begin, end, newerAlt, newOpenVars, newDecls, newerNeed, /*newNeedParents,*/ level, indexer, out );
-			} else {
-				delete adjType;
 			}
 		}
@@ -634,5 +625,5 @@
 	struct ArgPack {
 		std::size_t parent;                ///< Index of parent pack
-		std::unique_ptr<Expression> expr;  ///< The argument stored here
+		Expression* expr;                  ///< The argument stored here
 		Cost cost;                         ///< The cost of this argument
 		TypeEnvironment env;               ///< Environment for this pack
@@ -681,5 +672,5 @@
 			std::list<Expression*> exprs;
 			const ArgPack* pack = this;
-			if ( expr ) { exprs.push_front( expr.release() ); }
+			if ( expr ) { exprs.push_front( expr ); }
 			while ( pack->tupleStart == 0 ) {
 				pack = &packs[pack->parent];
@@ -688,5 +679,5 @@
 			}
 			// reset pack to appropriate tuple
-			expr.reset( new TupleExpr( exprs ) );
+			expr = new TupleExpr{ exprs };
 			tupleStart = pack->tupleStart - 1;
 			parent = pack->parent;
@@ -741,5 +732,5 @@
 
 						results.emplace_back(
-							i, expl.exprs[results[i].nextExpl].get(), copy(results[i].env),
+							i, expl.exprs[results[i].nextExpl], copy(results[i].env),
 							copy(results[i].need), copy(results[i].have),
 							copy(results[i].openVars), nextArg, nTuples, Cost::zero, nextExpl,
@@ -762,5 +753,5 @@
 							newResult.parent = i;
 							std::list<Expression*> emptyList;
-							newResult.expr.reset( new TupleExpr( emptyList ) );
+							newResult.expr = new TupleExpr{ emptyList };
 							argType = newResult.expr->get_result();
 						} else {
@@ -769,5 +760,5 @@
 							newResult.cost = results[i].cost;
 							newResult.tupleStart = results[i].tupleStart;
-							newResult.expr.reset( results[i].expr->clone() );
+							newResult.expr = results[i].expr->clone();
 							argType = newResult.expr->get_result();
 
@@ -819,5 +810,5 @@
 						// add new result
 						results.emplace_back(
-							i, expl.exprs.front().get(), move(env), copy(results[i].need),
+							i, expl.exprs.front(), move(env), copy(results[i].need),
 							copy(results[i].have), move(openVars), nextArg + 1,
 							nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
@@ -845,5 +836,5 @@
 			if ( results[i].hasExpl() ) {
 				const ExplodedActual& expl = results[i].getExpl( args );
-				Expression* expr = expl.exprs[results[i].nextExpl].get();
+				Expression* expr = expl.exprs[results[i].nextExpl];
 
 				TypeEnvironment env = results[i].env;
@@ -916,5 +907,5 @@
 
 				// consider only first exploded actual
-				Expression* expr = expl.exprs.front().get();
+				Expression* expr = expl.exprs.front();
 				Type* actualType = expr->result->clone();
 
@@ -1019,5 +1010,5 @@
 
 						results.emplace_back(
-							i, expl.exprs[results[i].nextExpl].get(), copy(results[i].env),
+							i, expl.exprs[results[i].nextExpl], copy(results[i].env),
 							copy(results[i].need), copy(results[i].have),
 							copy(results[i].openVars), nextArg, 0, Cost::zero, nextExpl,
@@ -1055,5 +1046,5 @@
 						// add new result
 						results.emplace_back(
-							i, expl.exprs.front().get(), move(env), copy(results[i].need),
+							i, expl.exprs.front(), move(env), copy(results[i].need),
 							copy(results[i].have), move(openVars), nextArg + 1, 0,
 							expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
@@ -1089,8 +1080,8 @@
 
 		// find function operators
-		static NameExpr *opExpr = new NameExpr( "?()" );
+		static auto *opExpr = new_static_root<NameExpr>( "?()" );
 		AlternativeFinder funcOpFinder( indexer, env );
 		// it's ok if there aren't any defined function ops
-		funcOpFinder.maybeFind( opExpr);
+		funcOpFinder.maybeFind( opExpr );
 		PRINT(
 			std::cerr << "known function ops:" << std::endl;
@@ -1121,6 +1112,6 @@
 				)
 				// check if the type is pointer to function
-				if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->result->stripReferences() ) ) {
-					if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->base ) ) {
+				if ( PointerType *pointer = dynamic_cast< PointerType* >( func->expr->get_result()->stripReferences() ) ) {
+					if ( FunctionType *function = dynamic_cast< FunctionType* >( pointer->get_base() ) ) {
 						Alternative newFunc( *func );
 						referenceToRvalueConversion( newFunc.expr, newFunc.cost );
@@ -1128,7 +1119,7 @@
 							std::back_inserter( candidates ) );
 					}
-				} else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->result->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
+				} else if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( func->expr->get_result()->stripReferences() ) ) { // handle ftype (e.g. *? on function pointer)
 					EqvClass eqvClass;
-					if ( func->env.lookup( typeInst->name, eqvClass ) && eqvClass.type ) {
+					if ( func->env.lookup( typeInst->get_name(), eqvClass ) && eqvClass.type ) {
 						if ( FunctionType *function = dynamic_cast< FunctionType* >( eqvClass.type ) ) {
 							Alternative newFunc( *func );
@@ -1159,7 +1150,7 @@
 					// check if type is a pointer to function
 					if ( PointerType* pointer = dynamic_cast<PointerType*>(
-							funcOp->expr->result->stripReferences() ) ) {
+							funcOp->expr->get_result()->stripReferences() ) ) {
 						if ( FunctionType* function =
-								dynamic_cast<FunctionType*>( pointer->base ) ) {
+								dynamic_cast<FunctionType*>( pointer->get_base() ) ) {
 							Alternative newFunc( *funcOp );
 							referenceToRvalueConversion( newFunc.expr, newFunc.cost );
@@ -1183,11 +1174,11 @@
 			PRINT(
 				ApplicationExpr *appExpr = strict_dynamic_cast< ApplicationExpr* >( withFunc.expr );
-				PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->function->result );
-				FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->base );
-				std::cerr << "Case +++++++++++++ " << appExpr->function << std::endl;
+				PointerType *pointer = strict_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() );
+				FunctionType *function = strict_dynamic_cast< FunctionType* >( pointer->get_base() );
+				std::cerr << "Case +++++++++++++ " << appExpr->get_function() << std::endl;
 				std::cerr << "formals are:" << std::endl;
-				printAll( function->parameters, std::cerr, 8 );
+				printAll( function->get_parameters(), std::cerr, 8 );
 				std::cerr << "actuals are:" << std::endl;
-				printAll( appExpr->args, std::cerr, 8 );
+				printAll( appExpr->get_args(), std::cerr, 8 );
 				std::cerr << "bindings are:" << std::endl;
 				withFunc.env.print( std::cerr, 8 );
@@ -1230,5 +1221,5 @@
 	bool isLvalue( Expression *expr ) {
 		// xxx - recurse into tuples?
-		return expr->result && ( expr->result->get_lvalue() || dynamic_cast< ReferenceType * >( expr->result ) );
+		return expr->result && ( expr->get_result()->get_lvalue() || dynamic_cast< ReferenceType * >( expr->get_result() ) );
 	}
 
@@ -1265,5 +1256,4 @@
 				componentExprs.push_back( restructureCast( idx, toType->getComponent( i ), isGenerated ) );
 			}
-			delete argExpr;
 			assert( componentExprs.size() > 0 );
 			// produce the tuple of casts
@@ -1346,4 +1336,13 @@
 	}
 
+	namespace {
+		/// Gets name from untyped member expression (member must be NameExpr)
+		const std::string& get_member_name( UntypedMemberExpr *memberExpr ) {
+			NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() );
+			assert( nameExpr );
+			return nameExpr->get_name();
+		}
+	}
+
 	void AlternativeFinder::Finder::postvisit( UntypedMemberExpr *memberExpr ) {
 		AlternativeFinder funcFinder( indexer, env );
@@ -1354,11 +1353,10 @@
 			Expression * aggrExpr = agg->expr->clone();
 			referenceToRvalueConversion( aggrExpr, cost );
-			std::unique_ptr<Expression> guard( aggrExpr );
 
 			// find member of the given type
 			if ( StructInstType *structInst = dynamic_cast< StructInstType* >( aggrExpr->get_result() ) ) {
-				addAggMembers( structInst, aggrExpr, cost, agg->env, memberExpr->get_member() );
+				addAggMembers( structInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
 			} else if ( UnionInstType *unionInst = dynamic_cast< UnionInstType* >( aggrExpr->get_result() ) ) {
-				addAggMembers( unionInst, aggrExpr, cost, agg->env, memberExpr->get_member() );
+				addAggMembers( unionInst, aggrExpr, cost, agg->env, get_member_name(memberExpr) );
 			} else if ( TupleType * tupleType = dynamic_cast< TupleType * >( aggrExpr->get_result() ) ) {
 				addTupleMembers( tupleType, aggrExpr, cost, agg->env, memberExpr->get_member() );
@@ -1605,5 +1603,4 @@
 			alternatives.push_back( Alternative( new CommaExpr( newFirstArg->clone(), alt.expr->clone() ), alt.env, alt.cost ) );
 		} // for
-		delete newFirstArg;
 	}
 
Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc	(revision a8706fc00f87d52e8a2088039ea7e9d0d0ba8b7c)
+++ src/ResolvExpr/ConversionCost.cc	(revision eba74ba03a2c29999def828ffaf6afc87e2b40d1)
@@ -20,4 +20,5 @@
 #include <string>                        // for operator==, string
 
+#include "Common/GC.h"                   // for new_static_root
 #include "ResolvExpr/Cost.h"             // for Cost
 #include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
@@ -351,6 +352,6 @@
 	void ConversionCost::postvisit( EnumInstType * ) {
 		static Type::Qualifiers q;
-		static BasicType integer( q, BasicType::SignedInt );
-		cost = costFunc( &integer, dest, indexer, env );  // safe if dest >= int
+		static BasicType* integer = new_static_root<BasicType>( q, BasicType::SignedInt );
+		cost = costFunc( integer, dest, indexer, env );  // safe if dest >= int
 		if ( cost < Cost::unsafe ) {
 			cost.incSafe();
Index: src/ResolvExpr/ExplodedActual.h
===================================================================
--- src/ResolvExpr/ExplodedActual.h	(revision a8706fc00f87d52e8a2088039ea7e9d0d0ba8b7c)
+++ src/ResolvExpr/ExplodedActual.h	(revision eba74ba03a2c29999def828ffaf6afc87e2b40d1)
@@ -16,5 +16,4 @@
 #pragma once
 
-#include <memory>
 #include <vector>
 
@@ -29,5 +28,5 @@
 		TypeEnvironment env;
 		Cost cost;
-		std::vector< std::unique_ptr<Expression> > exprs;
+		std::vector< Expression* > exprs;
 
 		ExplodedActual() : env(), cost(Cost::zero), exprs() {}
Index: src/ResolvExpr/ResolveTypeof.cc
===================================================================
--- src/ResolvExpr/ResolveTypeof.cc	(revision a8706fc00f87d52e8a2088039ea7e9d0d0ba8b7c)
+++ src/ResolvExpr/ResolveTypeof.cc	(revision eba74ba03a2c29999def828ffaf6afc87e2b40d1)
@@ -70,9 +70,5 @@
 			Expression * newExpr = resolveInVoidContext( typeofType->expr, indexer );
 			assert( newExpr->result && ! newExpr->result->isVoid() );
-			Type * newType = newExpr->result;
-			newExpr->result = nullptr;
-			delete typeofType;
-			delete newExpr;
-			return newType;
+			return newExpr->result;
 		} // if
 		return typeofType;
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision a8706fc00f87d52e8a2088039ea7e9d0d0ba8b7c)
+++ src/ResolvExpr/Resolver.cc	(revision eba74ba03a2c29999def828ffaf6afc87e2b40d1)
@@ -22,4 +22,5 @@
 #include "Alternative.h"                 // for Alternative, AltList
 #include "AlternativeFinder.h"           // for AlternativeFinder, resolveIn...
+#include "Common/GC.h"                   // for new_generation, collect_young
 #include "Common/PassVisitor.h"          // for PassVisitor
 #include "Common/SemanticError.h"        // for SemanticError
@@ -158,5 +159,4 @@
 					castExpr->arg = nullptr;
 					std::swap( expr->env, castExpr->env );
-					delete castExpr;
 				}
 			}
@@ -167,4 +167,7 @@
 		void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, bool adjust = false, bool prune = true, bool failFast = true) {
 			assertf( untyped, "expected a non-null expression." );
+
+			auto guard = new_generation();  // set up GC generation for this top-level expression
+
 			TypeEnvironment env;
 			AlternativeFinder finder( indexer, env );
@@ -207,7 +210,9 @@
 			Alternative & choice = winners.front();
 			if ( findDeletedExpr( choice.expr ) ) {
+				trace( choice.expr );
 				SemanticError( choice.expr, "Unique best alternative includes deleted identifier in " );
 			}
 			alt = std::move( choice );
+			trace( alt );
 		}
 
@@ -218,5 +223,4 @@
 			findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, adjust, prune, failFast );
 			finishExpr( choice.expr, choice.env, untyped->env );
-			delete untyped;
 			untyped = choice.expr;
 			choice.expr = nullptr;
@@ -241,20 +245,14 @@
 		assertf( expr, "expected a non-null expression." );
 
-		static CastExpr untyped( nullptr ); // cast to void
+		auto untyped = new CastExpr{ expr }; // cast to void
 
 		// set up and resolve expression cast to void
-		untyped.arg = expr;
 		Alternative choice;
-		findUnfinishedKindExpression( &untyped, choice, indexer, "", standardAlternativeFilter, true );
+		findUnfinishedKindExpression( untyped, choice, indexer, "", standardAlternativeFilter, true );
 		CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
 		env = std::move( choice.env );
 
 		// clean up resolved expression
-		Expression * ret = castExpr->arg;
-		castExpr->arg = nullptr;
-
-		// unlink the arg so that it isn't deleted twice at the end of the program
-		untyped.arg = nullptr;
-		return ret;
+		return castExpr->arg;
 	}
 
@@ -264,5 +262,4 @@
 		Expression * newExpr = resolveInVoidContext( untyped, indexer, env );
 		finishExpr( newExpr, env, untyped->env );
-		delete untyped;
 		untyped = newExpr;
 	}
@@ -445,5 +442,4 @@
 				castExpr->arg = nullptr;
 				std::swap( newExpr->env, castExpr->env );
-				delete castExpr;
 			}
 			caseStmt->condition = newExpr;
@@ -745,5 +741,4 @@
 		// and newExpr may already have inferParams of its own, so a simple swap is not sufficient.
 		newExpr->spliceInferParams( initExpr );
-		delete initExpr;
 
 		// get the actual object's type (may not exactly match what comes back from the resolver due to conversions)
@@ -763,5 +758,4 @@
 							ce->set_arg( nullptr );
 							std::swap( ce->env, newExpr->env );
-							delete ce;
 						}
 					}
@@ -814,8 +808,6 @@
 		// could not find valid constructor, or found an intrinsic constructor
 		// fall back on C-style initializer
-		delete ctorInit->get_ctor();
-		ctorInit->set_ctor( NULL );
-		delete ctorInit->get_dtor();
-		ctorInit->set_dtor( NULL );
+		ctorInit->set_ctor( nullptr );
+		ctorInit->set_dtor( nullptr );
 		maybeAccept( ctorInit->get_init(), *visitor );
 	}
@@ -843,5 +835,4 @@
 
 		// found a constructor - can get rid of C-style initializer
-		delete ctorInit->init;
 		ctorInit->init = nullptr;
 
@@ -850,10 +841,8 @@
 		// to clean up generated code.
 		if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) {
-			delete ctorInit->ctor;
 			ctorInit->ctor = nullptr;
 		}
 
 		if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) {
-			delete ctorInit->dtor;
 			ctorInit->dtor = nullptr;
 		}
Index: src/ResolvExpr/TypeEnvironment.cc
===================================================================
--- src/ResolvExpr/TypeEnvironment.cc	(revision a8706fc00f87d52e8a2088039ea7e9d0d0ba8b7c)
+++ src/ResolvExpr/TypeEnvironment.cc	(revision eba74ba03a2c29999def828ffaf6afc87e2b40d1)
@@ -19,5 +19,7 @@
 #include <utility>                     // for pair
 
+#include "Common/PassVisitor.h"        // for PassVisitor<GcTracer>
 #include "Common/utility.h"            // for maybeClone
+#include "SynTree/GcTracer.h"          // for PassVisitor<GcTracer>
 #include "SynTree/Type.h"              // for Type, FunctionType, Type::Fora...
 #include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
@@ -59,11 +61,6 @@
 	EqvClass &EqvClass::operator=( const EqvClass &other ) {
 		if ( this == &other ) return *this;
-		delete type;
 		initialize( other, *this );
 		return *this;
-	}
-
-	EqvClass::~EqvClass() {
-		delete type;
 	}
 
@@ -147,5 +144,4 @@
 ///         std::cerr << " bound to variable " << *theClass->vars.begin() << std::endl;
 					sub.add( *theVar, newTypeInst );
-					delete newTypeInst;
 				} // if
 			} // for
@@ -188,7 +184,5 @@
 					if ( secondClass->type ) {
 						if ( newClass.type ) {
-							Type *newType = combineFunc( newClass.type, secondClass->type );
-							delete newClass.type;
-							newClass.type = newType;
+							newClass.type = combineFunc( newClass.type, secondClass->type );
 							newClass.allowWidening = newClass.allowWidening && secondClass->allowWidening;
 						} else {
@@ -230,4 +224,11 @@
 		return out;
 	}
+
+	PassVisitor<GcTracer> & operator<<( PassVisitor<GcTracer> & gc, const TypeEnvironment & env ) {
+		for ( const EqvClass & c : env ) {
+			maybeAccept( c.type, gc );
+		}
+		return gc;
+	}
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/TypeEnvironment.h
===================================================================
--- src/ResolvExpr/TypeEnvironment.h	(revision a8706fc00f87d52e8a2088039ea7e9d0d0ba8b7c)
+++ src/ResolvExpr/TypeEnvironment.h	(revision eba74ba03a2c29999def828ffaf6afc87e2b40d1)
@@ -26,4 +26,8 @@
 #include "SynTree/Type.h"              // for Type, Type::ForallList
 #include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
+
+template< typename Pass >
+class PassVisitor;
+class GcTracer;
 
 namespace ResolvExpr {
@@ -76,5 +80,4 @@
 		EqvClass( const EqvClass &other );
 		EqvClass &operator=( const EqvClass &other );
-		~EqvClass();
 		void print( std::ostream &os, Indenter indent = {} ) const;
 	};
@@ -126,4 +129,6 @@
 
 	std::ostream & operator<<( std::ostream & out, const TypeEnvironment & env );
+
+	PassVisitor<GcTracer> & operator<<( PassVisitor<GcTracer> & gc, const TypeEnvironment & env );
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/Unify.cc
===================================================================
--- src/ResolvExpr/Unify.cc	(revision a8706fc00f87d52e8a2088039ea7e9d0d0ba8b7c)
+++ src/ResolvExpr/Unify.cc	(revision eba74ba03a2c29999def828ffaf6afc87e2b40d1)
@@ -17,5 +17,4 @@
 #include <iterator>               // for back_insert_iterator, back_inserter
 #include <map>                    // for _Rb_tree_const_iterator, _Rb_tree_i...
-#include <memory>                 // for unique_ptr
 #include <set>                    // for set
 #include <string>                 // for string, operator==, operator!=, bas...
@@ -99,8 +98,5 @@
 		findOpenVars( newSecond, openVars, closedVars, needAssertions, haveAssertions, true );
 
-		bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
-		delete newFirst;
-		delete newSecond;
-		return result;
+		return unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
 	}
 
@@ -123,8 +119,5 @@
 ///   newSecond->print( std::cerr );
 ///   std::cerr << std::endl;
-		bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
-		delete newFirst;
-		delete newSecond;
-		return result;
+		return unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
 	}
 
@@ -171,10 +164,9 @@
 				Type *common = 0;
 				// attempt to unify equivalence class type (which has qualifiers stripped, so they must be restored) with the type to bind to
-				std::unique_ptr< Type > newType( curClass.type->clone() );
+				Type* newType = curClass.type->clone();
 				newType->get_qualifiers() = typeInst->get_qualifiers();
-				if ( unifyInexact( newType.get(), other, env, needAssertions, haveAssertions, openVars, widenMode & WidenMode( curClass.allowWidening, true ), indexer, common ) ) {
+				if ( unifyInexact( newType, other, env, needAssertions, haveAssertions, openVars, widenMode & WidenMode( curClass.allowWidening, true ), indexer, common ) ) {
 					if ( common ) {
 						common->get_qualifiers() = Type::Qualifiers();
-						delete curClass.type;
 						curClass.type = common;
 						env.add( curClass );
@@ -239,5 +231,4 @@
 				if ( common ) {
 					common->get_qualifiers() = Type::Qualifiers();
-					delete class1.type;
 					class1.type = common;
 				} // if
@@ -272,6 +263,4 @@
 			env.add( newClass );
 		} // if
-		delete type1;
-		delete type2;
 		return result;
 	}
@@ -282,12 +271,5 @@
 		findOpenVars( type2, openVars, closedVars, needAssertions, haveAssertions, true );
 		Type *commonType = 0;
-		if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType ) ) {
-			if ( commonType ) {
-				delete commonType;
-			} // if
-			return true;
-		} else {
-			return false;
-		} // if
+		return unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType );
 	}
 
@@ -483,5 +465,5 @@
 
 	template< typename Iterator, typename Func >
-	std::unique_ptr<Type> combineTypes( Iterator begin, Iterator end, Func & toType ) {
+	Type* combineTypes( Iterator begin, Iterator end, Func & toType ) {
 		std::list< Type * > types;
 		for ( ; begin != end; ++begin ) {
@@ -489,5 +471,5 @@
 			flatten( toType( *begin ), back_inserter( types ) );
 		}
-		return std::unique_ptr<Type>( new TupleType( Type::Qualifiers(), types ) );
+		return new TupleType{ Type::Qualifiers(), types };
 	}
 
@@ -504,8 +486,8 @@
 			if ( isTtype1 && ! isTtype2 ) {
 				// combine all of the things in list2, then unify
-				return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
+				return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
 			} else if ( isTtype2 && ! isTtype1 ) {
 				// combine all of the things in list1, then unify
-				return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
+				return unifyExact( combineTypes( list1Begin, list1End, get_type ), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
 			} else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) {
 				return false;
@@ -517,5 +499,5 @@
 			Type * t1 = (*list1Begin)->get_type();
 			if ( Tuples::isTtype( t1 ) ) {
-				return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
+				return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
 			} else return false;
 		} else if ( list2Begin != list2End ) {
@@ -523,5 +505,5 @@
 			Type * t2 = (*list2Begin)->get_type();
 			if ( Tuples::isTtype( t2 ) ) {
-				return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
+				return unifyExact( combineTypes( list1Begin, list1End, get_type ), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
 			} else return false;
 		} else {
@@ -544,5 +526,4 @@
 					// expand ttype parameter into its actual type
 					if ( eqvClass.type ) {
-						delete typeInst;
 						return eqvClass.type->clone();
 					}
@@ -569,5 +550,4 @@
 				dst.push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::C, nullptr, t, nullptr ) );
 			}
-			delete dcl;
 		}
 	}
@@ -578,6 +558,6 @@
 			// flatten the parameter lists for both functions so that tuple structure
 			// doesn't affect unification. Must be a clone so that the types don't change.
-			std::unique_ptr<FunctionType> flatFunc( functionType->clone() );
-			std::unique_ptr<FunctionType> flatOther( otherFunction->clone() );
+			FunctionType* flatFunc = functionType->clone();
+			FunctionType* flatOther = otherFunction->clone();
 			flattenList( flatFunc->get_parameters(), flatFunc->get_parameters(), env );
 			flattenList( flatOther->get_parameters(), flatOther->get_parameters(), env );
@@ -720,8 +700,8 @@
 			if ( isTtype1 && ! isTtype2 ) {
 				// combine all of the things in list2, then unify
-				return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
+				return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
 			} else if ( isTtype2 && ! isTtype1 ) {
 				// combine all of the things in list1, then unify
-				return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
+				return unifyExact( combineTypes( list1Begin, list1End, get_type ), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
 			} else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) {
 				return false;
@@ -733,5 +713,5 @@
 			Type * t1 = *list1Begin;
 			if ( Tuples::isTtype( t1 ) ) {
-				return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
+				return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
 			} else return false;
 		} else if ( list2Begin != list2End ) {
@@ -739,5 +719,5 @@
 			Type * t2 = *list2Begin;
 			if ( Tuples::isTtype( t2 ) ) {
-				return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
+				return unifyExact( combineTypes( list1Begin, list1End, get_type ), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
 			} else return false;
 		} else {
@@ -748,6 +728,6 @@
 	void Unify::postvisit(TupleType *tupleType) {
 		if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) {
-			std::unique_ptr<TupleType> flat1( tupleType->clone() );
-			std::unique_ptr<TupleType> flat2( otherTuple->clone() );
+			TupleType* flat1 = tupleType->clone();
+			TupleType* flat2 = otherTuple->clone();
 			std::list<Type *> types1, types2;
 
@@ -756,6 +736,6 @@
 			flat2->acceptMutator( expander );
 
-			flatten( flat1.get(), back_inserter( types1 ) );
-			flatten( flat2.get(), back_inserter( types2 ) );
+			flatten( flat1, back_inserter( types1 ) );
+			flatten( flat2, back_inserter( types2 ) );
 
 			result = unifyList( types1.begin(), types1.end(), types2.begin(), types2.end(), env, needAssertions, haveAssertions, openVars, indexer );
Index: src/ResolvExpr/Unify.h
===================================================================
--- src/ResolvExpr/Unify.h	(revision a8706fc00f87d52e8a2088039ea7e9d0d0ba8b7c)
+++ src/ResolvExpr/Unify.h	(revision eba74ba03a2c29999def828ffaf6afc87e2b40d1)
@@ -64,10 +64,5 @@
 	bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
 		std::list< Type* > commonTypes;
-		if ( unifyList( list1Begin, list1End, list2Begin, list2End, env, needAssertions, haveAssertions, openVars, indexer, commonTypes ) ) {
-			deleteAll( commonTypes );
-			return true;
-		} else {
-			return false;
-		} // if
+		return unifyList( list1Begin, list1End, list2Begin, list2End, env, needAssertions, haveAssertions, openVars, indexer, commonTypes );
 	}
 
