Index: src/AST/TypeSubstitution.cpp
===================================================================
--- src/AST/TypeSubstitution.cpp	(revision 7d0881c5d24fef8ba66a626f072330c3ad5d9d76)
+++ src/AST/TypeSubstitution.cpp	(revision 55b64769d5e1c45cb4b5d7f0b3dfa82322d8f3d2)
@@ -92,5 +92,5 @@
 namespace {
 	struct EnvTrimmer {
-		ptr<TypeSubstitution> env;
+		const TypeSubstitution * env;
 		TypeSubstitution * newEnv;
 		EnvTrimmer( const TypeSubstitution * env, TypeSubstitution * newEnv ) : env( env ), newEnv( newEnv ){}
@@ -108,11 +108,6 @@
 	if ( env ) {
 		TypeSubstitution * newEnv = new TypeSubstitution();
-#if TIME_TO_CONVERT_PASSES
 		Pass<EnvTrimmer> trimmer( env, newEnv );
 		expr->accept( trimmer );
-#else
-		(void)expr;
-		(void)env;
-#endif
 		return newEnv;
 	}
@@ -121,19 +116,15 @@
 
 void TypeSubstitution::normalize() {
-#if TIME_TO_CONVERT_PASSES
-	PassVisitor<Substituter> sub( *this, true );
+	Pass<Substituter> sub( *this, true );
 	do {
 		sub.pass.subCount = 0;
 		sub.pass.freeOnly = true;
 		for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) {
-			i->second = i->second->acceptMutator( sub );
+			i->second = i->second->accept( sub );
 		}
 	} while ( sub.pass.subCount );
-#endif
-}
-
-#if TIME_TO_CONVERT_PASSES
-
-Type * TypeSubstitution::Substituter::postmutate( TypeInstType *inst ) {
+}
+
+const Type * TypeSubstitution::Substituter::postvisit( const TypeInstType *inst ) {
 	BoundVarsType::const_iterator bound = boundVars.find( inst->name );
 	if ( bound != boundVars.end() ) return inst;
@@ -146,5 +137,5 @@
 		// Note: this does not prevent cycles in the general case, so it may be necessary to do something more sophisticated here.
 		// TODO: investigate preventing type variables from being bound to themselves in the first place.
-		if ( TypeInstType * replacement = i->second.as<TypeInstType>() ) {
+		if ( const TypeInstType * replacement = i->second.as<TypeInstType>() ) {
 			if ( inst->name == replacement->name ) {
 				return inst;
@@ -153,13 +144,14 @@
 		// std::cerr << "found " << inst->name << ", replacing with " << i->second << std::endl;
 		subCount++;
-		Type * newtype = i->second->clone();
-		newtype->get_qualifiers() |= inst->get_qualifiers();
-		delete inst;
-		// Note: need to recursively apply substitution to the new type because normalize does not substitute bound vars, but bound vars must be substituted when not in freeOnly mode.
-		return newtype->acceptMutator( *visitor );
-	} // if
-}
-
-Expression * TypeSubstitution::Substituter::postmutate( NameExpr * nameExpr ) {
+		ptr<Type> newType = i->second; // force clone if needed
+		add_qualifiers( newType, inst->qualifiers );
+		// Note: need to recursively apply substitution to the new type because normalize does not 
+		// substitute bound vars, but bound vars must be substituted when not in freeOnly mode.
+		newType = newType->accept( *visitor );
+		return newType.release();
+	} // if
+}
+
+const Expr * TypeSubstitution::Substituter::postvisit( const NameExpr * nameExpr ) {
 	VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name );
 	if ( i == sub.varEnv.end() ) {
@@ -168,45 +160,44 @@
 		subCount++;
 		delete nameExpr;
-		return i->second->clone();
-	} // if
-}
-
-void TypeSubstitution::Substituter::premutate( Type * type ) {
+		return i->second;
+	} // if
+}
+
+void TypeSubstitution::Substituter::previsit( const ParameterizedType * ptype ) {
 	GuardValue( boundVars );
 	// bind type variables from forall-qualifiers
 	if ( freeOnly ) {
-		for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
-			boundVars.insert( (*tyvar)->name );
+		for ( const TypeDecl * tyvar : ptype->forall ) {
+				boundVars.insert( tyvar->name );
 		} // for
 	} // if
 }
 
-template< typename TypeClass >
-void TypeSubstitution::Substituter::handleAggregateType( TypeClass * type ) {
+void TypeSubstitution::Substituter::handleAggregateType( const ReferenceToType * type ) {
 	GuardValue( boundVars );
 	// bind type variables from forall-qualifiers
 	if ( freeOnly ) {
-		for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) {
-			boundVars.insert( (*tyvar)->name );
+		for ( const TypeDecl * tyvar : type->forall ) {
+			boundVars.insert( tyvar->name );
 		} // for
 		// bind type variables from generic type instantiations
-		std::list< TypeDecl* > *baseParameters = type->get_baseParameters();
-		if ( baseParameters && ! type->parameters.empty() ) {
-			for ( std::list< TypeDecl* >::const_iterator tyvar = baseParameters->begin(); tyvar != baseParameters->end(); ++tyvar ) {
-				boundVars.insert( (*tyvar)->name );
-			} // for
-		} // if
-	} // if
-}
-
-void TypeSubstitution::Substituter::premutate( StructInstType * aggregateUseType ) {
+		if ( auto decl = type->aggr() ) {
+			const std::vector<ptr<TypeDecl>> &baseParameters =  decl->params;
+			if (! type->params.empty()) {
+				for ( const TypeDecl * tyvar : baseParameters ) {
+					boundVars.insert( tyvar->name );
+				} // for
+			} // if
+		}
+	} // if
+}
+
+void TypeSubstitution::Substituter::previsit( const StructInstType * aggregateUseType ) {
 	handleAggregateType( aggregateUseType );
 }
 
-void TypeSubstitution::Substituter::premutate( UnionInstType *aggregateUseType ) {
+void TypeSubstitution::Substituter::previsit( const UnionInstType *aggregateUseType ) {
 	handleAggregateType( aggregateUseType );
 }
-
-#endif
 
 } // namespace ast
Index: src/AST/TypeSubstitution.hpp
===================================================================
--- src/AST/TypeSubstitution.hpp	(revision 7d0881c5d24fef8ba66a626f072330c3ad5d9d76)
+++ src/AST/TypeSubstitution.hpp	(revision 55b64769d5e1c45cb4b5d7f0b3dfa82322d8f3d2)
@@ -155,18 +155,14 @@
 		Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
 
-#if TIME_TO_CONVERT_PASSES
-
-		Type * postmutate( TypeInstType * aggregateUseType );
-		Expression * postmutate( NameExpr * nameExpr );
+		const Type * postvisit( const TypeInstType * aggregateUseType );
+		const Expr * postvisit( const NameExpr * nameExpr );
 
 		/// Records type variable bindings from forall-statements
-		void premutate( Type * type );
+		void previsit( const ParameterizedType * 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 );
-
-#endif
+		void handleAggregateType( const ReferenceToType * type );
+
+		void previsit( const StructInstType * aggregateUseType );
+		void previsit( const UnionInstType * aggregateUseType );
 
 		const TypeSubstitution & sub;
