Index: src/ResolvExpr/AdjustExprType.cc
===================================================================
--- src/ResolvExpr/AdjustExprType.cc	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/ResolvExpr/AdjustExprType.cc	(revision f53acdf88f0790f441b622ba4624c865224726a7)
@@ -100,35 +100,36 @@
 
 namespace {
-	struct AdjustExprType_new final : public ast::WithShortCircuiting {
+	class AdjustExprType_new final : public ast::WithShortCircuiting {
+		const ast::SymbolTable & symtab;
+	public:
 		const ast::TypeEnvironment & tenv;
-		const ast::SymbolTable & symtab;
 
 		AdjustExprType_new( const ast::TypeEnvironment & e, const ast::SymbolTable & syms )
-		: tenv( e ), symtab( syms ) {}
+		: symtab( syms ), tenv( e ) {}
 
-		void premutate( const ast::VoidType * ) { visit_children = false; }
-		void premutate( const ast::BasicType * ) { visit_children = false; }
-		void premutate( const ast::PointerType * ) { visit_children = false; }
-		void premutate( const ast::ArrayType * ) { visit_children = false; }
-		void premutate( const ast::FunctionType * ) { visit_children = false; }
-		void premutate( const ast::StructInstType * ) { visit_children = false; }
-		void premutate( const ast::UnionInstType * ) { visit_children = false; }
-		void premutate( const ast::EnumInstType * ) { visit_children = false; }
-		void premutate( const ast::TraitInstType * ) { visit_children = false; }
-		void premutate( const ast::TypeInstType * ) { visit_children = false; }
-		void premutate( const ast::TupleType * ) { visit_children = false; }
-		void premutate( const ast::VarArgsType * ) { visit_children = false; }
-		void premutate( const ast::ZeroType * ) { visit_children = false; }
-		void premutate( const ast::OneType * ) { visit_children = false; }
+		void previsit( const ast::VoidType * ) { visit_children = false; }
+		void previsit( const ast::BasicType * ) { visit_children = false; }
+		void previsit( const ast::PointerType * ) { visit_children = false; }
+		void previsit( const ast::ArrayType * ) { visit_children = false; }
+		void previsit( const ast::FunctionType * ) { visit_children = false; }
+		void previsit( const ast::StructInstType * ) { visit_children = false; }
+		void previsit( const ast::UnionInstType * ) { visit_children = false; }
+		void previsit( const ast::EnumInstType * ) { visit_children = false; }
+		void previsit( const ast::TraitInstType * ) { visit_children = false; }
+		void previsit( const ast::TypeInstType * ) { visit_children = false; }
+		void previsit( const ast::TupleType * ) { visit_children = false; }
+		void previsit( const ast::VarArgsType * ) { visit_children = false; }
+		void previsit( const ast::ZeroType * ) { visit_children = false; }
+		void previsit( const ast::OneType * ) { visit_children = false; }
 
-		const ast::Type * postmutate( const ast::ArrayType * at ) {
+		const ast::Type * postvisit( const ast::ArrayType * at ) {
 			return new ast::PointerType{ at->base, at->qualifiers };
 		}
 
-		const ast::Type * postmutate( const ast::FunctionType * ft ) {
+		const ast::Type * postvisit( const ast::FunctionType * ft ) {
 			return new ast::PointerType{ ft };
 		}
 
-		const ast::Type * postmutate( const ast::TypeInstType * inst ) {
+		const ast::Type * postvisit( const ast::TypeInstType * inst ) {
 			// replace known function-type-variables with pointer-to-function
 			if ( const ast::EqvClass * eqvClass = tenv.lookup( inst->name ) ) {
Index: src/ResolvExpr/CandidateFinder.cpp
===================================================================
--- src/ResolvExpr/CandidateFinder.cpp	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/ResolvExpr/CandidateFinder.cpp	(revision f53acdf88f0790f441b622ba4624c865224726a7)
@@ -370,7 +370,5 @@
 							// push empty tuple expression
 							newResult.parent = i;
-							std::vector< ast::ptr< ast::Expr > > emptyList;
-							newResult.expr = 
-								new ast::TupleExpr{ CodeLocation{}, move( emptyList ) };
+							newResult.expr = new ast::TupleExpr{ CodeLocation{}, {} };
 							argType = newResult.expr->result;
 						} else {
@@ -548,5 +546,5 @@
 		genStart = genEnd;
 
-		return genEnd != results.size();
+		return genEnd != results.size();  // were any new results added?
 	}
 
@@ -594,7 +592,8 @@
 
 	/// Actually visits expressions to find their candidate interpretations
-	struct Finder final : public ast::WithShortCircuiting {
+	class Finder final : public ast::WithShortCircuiting {
+		const ast::SymbolTable & symtab;
+	public:
 		CandidateFinder & selfFinder;
-		const ast::SymbolTable & symtab;
 		CandidateList & candidates;
 		const ast::TypeEnvironment & tenv;
@@ -602,5 +601,5 @@
 
 		Finder( CandidateFinder & f )
-		: selfFinder( f ), symtab( f.symtab ), candidates( f.candidates ), tenv( f.env ), 
+		: symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ), 
 		  targetType( f.targetType ) {}
 		
@@ -676,6 +675,6 @@
 			ast::TypeEnvironment funcEnv{ func->env };
 			makeUnifiableVars( funcType, funcOpen, funcNeed );
-			// add all type variables as open variables now so that those not used in the parameter 
-			// list are still considered open
+			// add all type variables as open variables now so that those not used in the 
+			// parameter list are still considered open
 			funcEnv.add( funcType->forall );
 
@@ -1558,5 +1557,5 @@
 		std::vector< std::string > errors;
 		for ( CandidateRef & candidate : candidates ) {
-			satisfyAssertions( candidate, symtab, satisfied, errors );
+			satisfyAssertions( candidate, localSyms, satisfied, errors );
 		}
 
@@ -1613,5 +1612,5 @@
 			r->expr = ast::mutate_field( 
 				r->expr.get(), &ast::Expr::result, 
-				adjustExprType( r->expr->result, r->env, symtab ) );
+				adjustExprType( r->expr->result, r->env, localSyms ) );
 		}
 	}
@@ -1631,5 +1630,5 @@
 
 	for ( const auto & x : xs ) {
-		out.emplace_back( symtab, env );
+		out.emplace_back( localSyms, env );
 		out.back().find( x, ResolvMode::withAdjustment() );
 		
Index: src/ResolvExpr/CandidateFinder.hpp
===================================================================
--- src/ResolvExpr/CandidateFinder.hpp	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/ResolvExpr/CandidateFinder.hpp	(revision f53acdf88f0790f441b622ba4624c865224726a7)
@@ -28,12 +28,12 @@
 struct CandidateFinder {
 	CandidateList candidates;          ///< List of candidate resolutions
-	const ast::SymbolTable & symtab;   ///< Symbol table to lookup candidates
+	const ast::SymbolTable & localSyms;   ///< Symbol table to lookup candidates
 	const ast::TypeEnvironment & env;  ///< Substitutions performed in this resolution
 	ast::ptr< ast::Type > targetType;  ///< Target type for resolution
 
 	CandidateFinder( 
-		const ast::SymbolTable & symtab, const ast::TypeEnvironment & env, 
+		const ast::SymbolTable & syms, const ast::TypeEnvironment & env, 
 		const ast::Type * tt = nullptr )
-	: candidates(), symtab( symtab ), env( env ), targetType( tt ) {}
+	: candidates(), localSyms( syms ), env( env ), targetType( tt ) {}
 
 	/// Fill candidates with feasible resolutions for `expr`
Index: src/ResolvExpr/CommonType.cc
===================================================================
--- src/ResolvExpr/CommonType.cc	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/ResolvExpr/CommonType.cc	(revision f53acdf88f0790f441b622ba4624c865224726a7)
@@ -939,5 +939,5 @@
 			ast::ptr< ast::Type > result;
 			const ast::ReferenceType * ref1 = type1.as< ast::ReferenceType >();
-			const ast::ReferenceType * ref2 = type1.as< ast::ReferenceType >();
+			const ast::ReferenceType * ref2 = type2.as< ast::ReferenceType >();
 
 			if ( depth1 > depth2 ) {
Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/ResolvExpr/ConversionCost.cc	(revision f53acdf88f0790f441b622ba4624c865224726a7)
@@ -10,6 +10,6 @@
 // Created On       : Sun May 17 07:06:19 2015
 // Last Modified By : Andrew Beach
-// Last Modified On : Mon Jun 24 13:33:00 2019
-// Update Count     : 26
+// Last Modified On : Thr Jul  4 10:56:00 2019
+// Update Count     : 27
 //
 
@@ -764,4 +764,8 @@
 			cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
 		}
+	} else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
+		cost = Cost::zero;
+		// +1 for zero_t ->, +1 for disambiguation
+		cost.incSafe( maxIntCost + 2 );
 	}
 }
@@ -781,7 +785,4 @@
 			cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
 		}
-	} else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
-		cost = Cost::zero;
-		cost.incSafe( maxIntCost + 2 );
 	}
 }
Index: src/ResolvExpr/PolyCost.cc
===================================================================
--- src/ResolvExpr/PolyCost.cc	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/ResolvExpr/PolyCost.cc	(revision f53acdf88f0790f441b622ba4624c865224726a7)
@@ -58,11 +58,12 @@
 
 // TODO: When the old PolyCost is torn out get rid of the _new suffix.
-struct PolyCost_new {
+class PolyCost_new {
+	const ast::SymbolTable &symtab;
+public:
 	int result;
-	const ast::SymbolTable &symtab;
 	const ast::TypeEnvironment &env_;
 
-	PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) :
-		result( 0 ), symtab( symtab ), env_( env ) {}
+	PolyCost_new( const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) 
+	: symtab( symtab ), result( 0 ), env_( env ) {}
 
 	void previsit( const ast::TypeInstType * type ) {
Index: src/ResolvExpr/RenameVars.cc
===================================================================
--- src/ResolvExpr/RenameVars.cc	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/ResolvExpr/RenameVars.cc	(revision f53acdf88f0790f441b622ba4624c865224726a7)
@@ -19,4 +19,5 @@
 #include <utility>                 // for pair
 
+#include "AST/ForallSubstitutionTable.hpp"
 #include "AST/Pass.hpp"
 #include "AST/Type.hpp"
@@ -37,6 +38,7 @@
 		int resetCount = 0;
 		ScopedMap< std::string, std::string > nameMap;
+	public:
+		ast::ForallSubstitutionTable subs;
 
-	public:
 		void reset() {
 			level = 0;
@@ -44,8 +46,6 @@
 		}
 
-		using mapConstIterator = ScopedMap< std::string, std::string >::const_iterator;
-
 		void rename( TypeInstType * type ) {
-			mapConstIterator it = nameMap.find( type->name );
+			auto it = nameMap.find( type->name );
 			if ( it != nameMap.end() ) {
 				type->name = it->second;
@@ -65,7 +65,6 @@
 					// ditto for assertion names, the next level in
 					level++;
-					// acceptAll( td->assertions, *this );
-				} // for
-			} // if
+				}
+			}
 		}
 
@@ -77,10 +76,16 @@
 
 		const ast::TypeInstType * rename( const ast::TypeInstType * type ) {
-			mapConstIterator it = nameMap.find( type->name );
+			// re-linking of base type handled by WithForallSubstitutor
+
+			// rename
+			auto it = nameMap.find( type->name );
 			if ( it != nameMap.end() ) {
-				ast::TypeInstType * mutType = ast::mutate( type );
-				mutType->name = it->second;
-	            type = mutType;
+				// unconditionally mutate because map will *always* have different name, 
+				// if this mutates, will *always* have been mutated by ForallSubstitutor above
+				ast::TypeInstType * mut = ast::mutate( type );
+				mut->name = it->second;
+	            type = mut;
 			}
+
 			return type;
 		}
@@ -88,29 +93,32 @@
 		template<typename NodeT>
 		const NodeT * openLevel( const NodeT * type ) {
-			if ( !type->forall.empty() ) {
-				nameMap.beginScope();
-				// Load new names from this forall clause and perform renaming.
-				NodeT * mutType = ast::mutate( type );
-				for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) {
-					std::ostringstream output;
-					output << "_" << resetCount << "_" << level << "_" << td->name;
-					std::string newname( output.str() );
-					nameMap[ td->name ] = newname;
-					++level;
+			if ( type->forall.empty() ) return type;
+			
+			nameMap.beginScope();
 
-					ast::TypeDecl * decl = ast::mutate( td.get() );
-					decl->name = newname;
-					td = decl;
-				}
+			// Load new names from this forall clause and perform renaming.
+			NodeT * mutType = ast::mutate( type );
+			assert( type == mutType && "mutated type must be unique from ForallSubstitutor" );
+			for ( ast::ptr< ast::TypeDecl > & td : mutType->forall ) {
+				std::ostringstream output;
+				output << "_" << resetCount << "_" << level << "_" << td->name;
+				std::string newname =  output.str();
+				nameMap[ td->name ] = newname;
+				++level;
+
+				ast::TypeDecl * mutDecl = ast::mutate( td.get() );
+				assert( td == mutDecl && "mutated decl must be unique from ForallSubstitutor" );
+				mutDecl->name = newname;
+				// assertion above means `td = mutDecl;` is unnecessary
 			}
+			// assertion above means `type = mutType;` is unnecessary
+
 			return type;
 		}
 
-		template<typename NodeT>
-		const NodeT * closeLevel( const NodeT * type ) {
-			if ( !type->forall.empty() ) {
-				nameMap.endScope();
-			}
-			return type;
+		void closeLevel( const ast::ParameterizedType * type ) {
+			if ( type->forall.empty() ) return;
+			
+			nameMap.endScope();
 		}
 	};
@@ -119,5 +127,5 @@
 	RenamingData renaming;
 
-	struct RenameVars {
+	struct RenameVars_old {
 		void previsit( TypeInstType * instType ) {
 			renaming.openLevel( (Type*)instType );
@@ -130,4 +138,9 @@
 			renaming.closeLevel( type );
 		}
+	};
+	
+	struct RenameVars_new /*: public ast::WithForallSubstitutor*/ {
+		#warning when old RenameVars goes away, replace hack below with global pass inheriting from WithForallSubstitutor
+		ast::ForallSubstitutionTable & subs = renaming.subs;
 
 		const ast::FunctionType * previsit( const ast::FunctionType * type ) {
@@ -146,6 +159,6 @@
 			return renaming.rename( renaming.openLevel( type ) );
 		}
-		const ast::ParameterizedType * postvisit( const ast::ParameterizedType * type ) {
-			return renaming.closeLevel( type );
+		void postvisit( const ast::ParameterizedType * type ) {
+			renaming.closeLevel( type );
 		}
 	};
@@ -154,10 +167,10 @@
 
 void renameTyVars( Type * t ) {
-	PassVisitor<RenameVars> renamer;
+	PassVisitor<RenameVars_old> renamer;
 	t->accept( renamer );
 }
 
 const ast::Type * renameTyVars( const ast::Type * t ) {
-	ast::Pass<RenameVars> renamer;
+	ast::Pass<RenameVars_new> renamer;
 	return t->accept( renamer );
 }
Index: src/ResolvExpr/ResolveTypeof.cc
===================================================================
--- src/ResolvExpr/ResolveTypeof.cc	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/ResolvExpr/ResolveTypeof.cc	(revision f53acdf88f0790f441b622ba4624c865224726a7)
@@ -153,5 +153,5 @@
 			}
 
-			return newType;
+			return newType.release();
 		}
 	};
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/ResolvExpr/Resolver.cc	(revision f53acdf88f0790f441b622ba4624c865224726a7)
@@ -1108,5 +1108,5 @@
 
 		// set up and resolve expression cast to void
-		ast::CastExpr * untyped = new ast::CastExpr{ expr };
+		ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr };
 		CandidateRef choice = findUnfinishedKindExpression(
 			untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
@@ -1247,5 +1247,5 @@
 	};
 
-	void resolve( std::list< ast::ptr<ast::Decl> >& translationUnit ) {
+	void resolve( std::list< ast::ptr< ast::Decl > >& translationUnit ) {
 		ast::Pass< Resolver_new > resolver;
 		accept_all( translationUnit, resolver );
@@ -1281,5 +1281,5 @@
 		ast::ptr< ast::FunctionDecl > ret = functionDecl;
 		for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) {
-			const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i];
+			const ast::ptr< ast::DeclWithType > & d = functionDecl->type->params[i];
 
 			if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) {
@@ -1298,5 +1298,5 @@
 			}
 		}
-		return ret.get();
+		return ret.release();
 	}
 
Index: src/ResolvExpr/SpecCost.cc
===================================================================
--- src/ResolvExpr/SpecCost.cc	(revision 6f096d2341e25591a9d9435e4a28725954748a7a)
+++ src/ResolvExpr/SpecCost.cc	(revision f53acdf88f0790f441b622ba4624c865224726a7)
@@ -10,8 +10,9 @@
 // Created On       : Tue Oct 02 15:50:00 2018
 // Last Modified By : Andrew Beach
-// Last Modified On : Wed Jun 19 10:43:00 2019
-// Update Count     : 2
-//
-
+// Last Modified On : Wed Jul  3 11:07:00 2019
+// Update Count     : 3
+//
+
+#include <cassert>
 #include <limits>
 #include <list>
@@ -129,4 +130,12 @@
 			typename std::add_pointer<ast::Type const *(typename T::value_type const &)>::type;
 
+		#warning Should use a standard maybe_accept
+		void maybe_accept( ast::Type const * type ) {
+			if ( type ) {
+				auto node = type->accept( *visitor );
+				assert( node == nullptr || node == type );
+			}
+		}
+
 		// Update the minimum to the new lowest non-none value.
 		template<typename T>
@@ -134,5 +143,5 @@
 			for ( const auto & node : list ) {
 				count = -1;
-				mapper( node )->accept( *visitor );
+				maybe_accept( mapper( node ) );
 				if ( count != -1 && count < minimum ) minimum = count;
 			}
