Index: src/SynTree/TypeSubstitution.cc
===================================================================
--- src/SynTree/TypeSubstitution.cc	(revision 07c178f0653a2553f5c511a5a286acc54ad243e2)
+++ src/SynTree/TypeSubstitution.cc	(revision e9a715d38423178893a33deb3484b23f09ed95ca)
@@ -107,26 +107,27 @@
 
 void TypeSubstitution::normalize() {
+	PassVisitor<Substituter> sub( *this, true );
 	do {
-		subCount = 0;
-		freeOnly = true;
+		sub.pass.subCount = 0;
+		sub.pass.freeOnly = true;
 		for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
-			i->second = i->second->acceptMutator( *this );
+			i->second = i->second->acceptMutator( sub );
 		}
-	} while ( subCount );
-}
-
-Type * TypeSubstitution::mutate( TypeInstType *inst ) {
-	BoundVarsType::const_iterator bound = boundVars.find( inst->get_name() );
+	} while ( sub.pass.subCount );
+}
+
+Type * TypeSubstitution::Substituter::postmutate( TypeInstType *inst ) {
+	BoundVarsType::const_iterator bound = boundVars.find( inst->name );
 	if ( bound != boundVars.end() ) return inst;
 
-	TypeEnvType::const_iterator i = typeEnv.find( inst->get_name() );
-	if ( i == typeEnv.end() ) {
+	TypeEnvType::const_iterator i = sub.typeEnv.find( inst->get_name() );
+	if ( i == sub.typeEnv.end() ) {
 		return inst;
 	} else {
-///	    std::cout << "found " << inst->get_name() << ", replacing with ";
-///	    i->second->print( std::cout );
-///	    std::cout << std::endl;
+///	    std::cerr << "found " << inst->get_name() << ", replacing with ";
+///	    i->second->print( std::cerr );
+///	    std::cerr << std::endl;
 		subCount++;
-		Type *newtype = i->second->clone();
+		Type * newtype = i->second->clone();
 		newtype->get_qualifiers() |= inst->get_qualifiers();
 		delete inst;
@@ -135,7 +136,7 @@
 }
 
-Expression * TypeSubstitution::mutate( NameExpr *nameExpr ) {
-	VarEnvType::const_iterator i = varEnv.find( nameExpr->get_name() );
-	if ( i == varEnv.end() ) {
+Expression * TypeSubstitution::Substituter::postmutate( NameExpr * nameExpr ) {
+	VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name );
+	if ( i == sub.varEnv.end() ) {
 		return nameExpr;
 	} else {
@@ -146,87 +147,38 @@
 }
 
-template< typename TypeClass >
-Type *TypeSubstitution::handleType( TypeClass *type ) {
-	ValueGuard<BoundVarsType> oldBoundVars( boundVars );
+void TypeSubstitution::Substituter::premutate( Type * type ) {
+	GuardValue( boundVars );
 	// bind type variables from forall-qualifiers
 	if ( freeOnly ) {
-		for ( Type::ForallList::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
-			boundVars.insert( (*tyvar )->get_name() );
+		for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
+			boundVars.insert( (*tyvar)->name );
 		} // for
 	} // if
-	Type *ret = Mutator::mutate( type );
-	return ret;
 }
 
 template< typename TypeClass >
-Type *TypeSubstitution::handleAggregateType( TypeClass *type ) {
-	ValueGuard<BoundVarsType> oldBoundVars( boundVars );
+void TypeSubstitution::Substituter::handleAggregateType( TypeClass * type ) {
+	GuardValue( boundVars );
 	// bind type variables from forall-qualifiers
 	if ( freeOnly ) {
-		for ( Type::ForallList::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
-			boundVars.insert( (*tyvar )->get_name() );
+		for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
+			boundVars.insert( (*tyvar)->name );
 		} // for
 		// bind type variables from generic type instantiations
 		std::list< TypeDecl* > *baseParameters = type->get_baseParameters();
-		if ( baseParameters && ! type->get_parameters().empty() ) {
+		if ( baseParameters && ! type->parameters.empty() ) {
 			for ( std::list< TypeDecl* >::const_iterator tyvar = baseParameters->begin(); tyvar != baseParameters->end(); ++tyvar ) {
-				boundVars.insert( (*tyvar)->get_name() );
+				boundVars.insert( (*tyvar)->name );
 			} // for
 		} // if
 	} // if
-	Type *ret = Mutator::mutate( type );
-	return ret;
-}
-
-Type * TypeSubstitution::mutate( VoidType *voidType ) {
-	return handleType( voidType );
-}
-
-Type * TypeSubstitution::mutate( BasicType *basicType ) {
-	return handleType( basicType );
-}
-
-Type * TypeSubstitution::mutate( PointerType *pointerType ) {
-	return handleType( pointerType );
-}
-
-Type * TypeSubstitution::mutate( ArrayType *arrayType ) {
-	return handleType( arrayType );
-}
-
-Type * TypeSubstitution::mutate( FunctionType *functionType ) {
-	return handleType( functionType );
-}
-
-Type * TypeSubstitution::mutate( StructInstType *aggregateUseType ) {
-	return handleAggregateType( aggregateUseType );
-}
-
-Type * TypeSubstitution::mutate( UnionInstType *aggregateUseType ) {
-	return handleAggregateType( aggregateUseType );
-}
-
-Type * TypeSubstitution::mutate( EnumInstType *aggregateUseType ) {
-	return handleType( aggregateUseType );
-}
-
-Type * TypeSubstitution::mutate( TraitInstType *aggregateUseType ) {
-	return handleType( aggregateUseType );
-}
-
-Type * TypeSubstitution::mutate( TupleType *tupleType ) {
-	return handleType( tupleType );
-}
-
-Type * TypeSubstitution::mutate( VarArgsType *varArgsType ) {
-	return handleType( varArgsType );
-}
-
-Type * TypeSubstitution::mutate( ZeroType *zeroType ) {
-	return handleType( zeroType );
-}
-
-Type * TypeSubstitution::mutate( OneType *oneType ) {
-	return handleType( oneType );
+}
+
+void TypeSubstitution::Substituter::premutate( StructInstType * aggregateUseType ) {
+	handleAggregateType( aggregateUseType );
+}
+
+void TypeSubstitution::Substituter::premutate( UnionInstType *aggregateUseType ) {
+	handleAggregateType( aggregateUseType );
 }
 
Index: src/SynTree/TypeSubstitution.h
===================================================================
--- src/SynTree/TypeSubstitution.h	(revision 07c178f0653a2553f5c511a5a286acc54ad243e2)
+++ src/SynTree/TypeSubstitution.h	(revision e9a715d38423178893a33deb3484b23f09ed95ca)
@@ -27,9 +27,7 @@
 #include "SynTree/Declaration.h"   // for TypeDecl, Declaration (ptr only)
 #include "SynTree/Expression.h"    // for Expression (ptr only), NameExpr (p...
-#include "SynTree/Mutator.h"       // for Mutator
 #include "SynTree/Type.h"          // for Type, ArrayType (ptr only), BasicT...
 
-class TypeSubstitution : public Mutator {
-	typedef Mutator Parent;
+class TypeSubstitution {
   public:
 	TypeSubstitution();
@@ -64,25 +62,7 @@
 	TypeSubstitution *clone() const { return new TypeSubstitution( *this ); }
   private:
-	virtual Type* mutate(TypeInstType *aggregateUseType);
-	virtual Expression* mutate(NameExpr *nameExpr);
 
-	/// Records type variable bindings from forall-statements
-	template< typename TypeClass > Type *handleType( TypeClass *type );
-	/// Records type variable bindings from forall-statements and instantiations of generic types
-	template< typename TypeClass > Type *handleAggregateType( TypeClass *type );
-
-	virtual Type* mutate(VoidType *basicType);
-	virtual Type* mutate(BasicType *basicType);
-	virtual Type* mutate(PointerType *pointerType);
-	virtual Type* mutate(ArrayType *arrayType);
-	virtual Type* mutate(FunctionType *functionType);
-	virtual Type* mutate(StructInstType *aggregateUseType);
-	virtual Type* mutate(UnionInstType *aggregateUseType);
-	virtual Type* mutate(EnumInstType *aggregateUseType);
-	virtual Type* mutate(TraitInstType *aggregateUseType);
-	virtual Type* mutate(TupleType *tupleType);
-	virtual Type* mutate(VarArgsType *varArgsType);
-	virtual Type* mutate(ZeroType *zeroType);
-	virtual Type* mutate(OneType *oneType);
+	// Mutator that performs the substitution
+	struct Substituter;
 
 	// TODO: worry about traversing into a forall-qualified function type or type decl with assertions
@@ -97,10 +77,6 @@
 	typedef std::map< std::string, Type* > TypeEnvType;
 	typedef std::map< std::string, Expression* > VarEnvType;
-	typedef std::set< std::string > BoundVarsType;
 	TypeEnvType typeEnv;
 	VarEnvType varEnv;
-	BoundVarsType boundVars;
-	int subCount;
-	bool freeOnly;
 };
 
@@ -134,20 +110,44 @@
 
 template< typename FormalIterator, typename ActualIterator >
-TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin )
-{
+TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
 	add( formalBegin, formalEnd, actualBegin );
 }
+
+// include needs to happen after TypeSubstitution is defined so that both TypeSubstitution and
+// PassVisitor are defined before PassVisitor implementation accesses TypeSubstitution internals.
+#include "Common/PassVisitor.h"
+
+// definitition must happen after PassVisitor is included so that WithGuards can be used
+struct TypeSubstitution::Substituter : public WithGuards {
+		Substituter( TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
+
+		Type * postmutate( TypeInstType * aggregateUseType );
+		Expression * postmutate( NameExpr * nameExpr );
+
+		/// Records type variable bindings from forall-statements
+		void premutate( Type * type );
+		/// Records type variable bindings from forall-statements and instantiations of generic types
+		template< typename TypeClass > void handleAggregateType( TypeClass * type );
+
+		void premutate( StructInstType * aggregateUseType );
+		void premutate( UnionInstType * aggregateUseType );
+
+		TypeSubstitution & sub;
+		int subCount = 0;
+		bool freeOnly;
+		typedef std::set< std::string > BoundVarsType;
+		BoundVarsType boundVars;
+};
 
 template< typename SynTreeClass >
 int TypeSubstitution::apply( SynTreeClass *&input ) {
 	assert( input );
-	subCount = 0;
-	freeOnly = false;
-	input = dynamic_cast< SynTreeClass *>( input->acceptMutator( *this ) );
+	PassVisitor<Substituter> sub( *this, false );
+	input = dynamic_cast< SynTreeClass * >( input->acceptMutator( sub ) );
 	assert( input );
-///	std::cout << "substitution result is: ";
-///	newType->print( std::cout );
-///	std::cout << std::endl;
-	return subCount;
+///	std::cerr << "substitution result is: ";
+///	newType->print( std::cerr );
+///	std::cerr << std::endl;
+	return sub.pass.subCount;
 }
 
@@ -155,12 +155,11 @@
 int TypeSubstitution::applyFree( SynTreeClass *&input ) {
 	assert( input );
-	subCount = 0;
-	freeOnly = true;
-	input = dynamic_cast< SynTreeClass *>( input->acceptMutator( *this ) );
+	PassVisitor<Substituter> sub( *this, true );
+	input = dynamic_cast< SynTreeClass * >( input->acceptMutator( sub ) );
 	assert( input );
-///	std::cout << "substitution result is: ";
-///	newType->print( std::cout );
-///	std::cout << std::endl;
-	return subCount;
+///	std::cerr << "substitution result is: ";
+///	newType->print( std::cerr );
+///	std::cerr << std::endl;
+	return sub.pass.subCount;
 }
 
