Index: src/GenPoly/ScrubTyVars.h
===================================================================
--- src/GenPoly/ScrubTyVars.h	(revision ea6332d2c7319372654f557cb69ec651fdc92331)
+++ src/GenPoly/ScrubTyVars.h	(revision 0aedb015e118b2cda7cda2e8fd705450f6fc34cb)
@@ -18,4 +18,5 @@
 #include <cassert>            // for assert
 
+#include "Common/PassVisitor.h"
 #include "GenPoly.h"          // for TyVarMap, isPolyType, isDynType
 #include "SynTree/Mutator.h"  // for Mutator
@@ -27,5 +28,5 @@
 
 namespace GenPoly {
-	class ScrubTyVars : public Mutator {
+	struct ScrubTyVars : public WithVisitorRef<ScrubTyVars>, public WithShortCircuiting, public WithGuards {
 		/// Whether to scrub all type variables from the provided map, dynamic type variables from the provided map, or all type variables
 		enum ScrubMode { FromMap, DynamicFromMap, All };
@@ -51,10 +52,20 @@
 		static SynTreeClass *scrubAll( SynTreeClass *target );
 
-		virtual Type* mutate( TypeInstType *typeInst );
-		virtual Type* mutate( StructInstType *structInst );
-		virtual Type* mutate( UnionInstType *unionInst );
-		virtual Expression* mutate( SizeofExpr *szeof );
-		virtual Expression* mutate( AlignofExpr *algnof );
-		virtual Type* mutate( PointerType *pointer );
+		/// determine if children should be visited based on whether base type should be scrubbed.
+		void primeBaseScrub( Type * );
+
+		void premutate( TypeInstType * ) { visit_children = false; }
+		void premutate( StructInstType * ) { visit_children = false; }
+		void premutate( UnionInstType * ) { visit_children = false; }
+		void premutate( SizeofExpr * szeof ) { primeBaseScrub( szeof->type ); }
+		void premutate( AlignofExpr * algnof ) { primeBaseScrub( algnof->type ); }
+		void premutate( PointerType * pointer ) { primeBaseScrub( pointer->base ); }
+
+		Type * postmutate( TypeInstType * typeInst );
+		Type * postmutate( StructInstType * structInst );
+		Type * postmutate( UnionInstType * unionInst );
+		Expression * postmutate( SizeofExpr * szeof );
+		Expression * postmutate( AlignofExpr * algnof );
+		Type * postmutate( PointerType * pointer );
 
 	  private:
@@ -75,9 +86,11 @@
 		const TyVarMap *tyVars;  ///< Type variables to scrub
 		ScrubMode mode;          ///< which type variables to scrub? [FromMap]
+
+		Type * dynType = nullptr; ///< result of shouldScrub
 	};
 
 	template< typename SynTreeClass >
 	SynTreeClass * ScrubTyVars::scrub( SynTreeClass *target, const TyVarMap &tyVars ) {
-		ScrubTyVars scrubber( tyVars );
+		PassVisitor<ScrubTyVars> scrubber( tyVars );
 		return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );
 	}
@@ -85,5 +98,5 @@
 	template< typename SynTreeClass >
 	SynTreeClass * ScrubTyVars::scrubDynamic( SynTreeClass *target, const TyVarMap &tyVars ) {
-		ScrubTyVars scrubber( tyVars, ScrubTyVars::DynamicFromMap );
+		PassVisitor<ScrubTyVars> scrubber( tyVars, ScrubTyVars::DynamicFromMap );
 		return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );
 	}
@@ -91,5 +104,5 @@
 	template< typename SynTreeClass >
 	SynTreeClass * ScrubTyVars::scrubAll( SynTreeClass *target ) {
-		ScrubTyVars scrubber;
+		PassVisitor<ScrubTyVars> scrubber;
 		return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );
 	}
