Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision a2f920fd2c573edb4b70470fe5d94960bd140fed)
+++ src/GenPoly/Box.cc	(revision 3bb195cb021bb5008ad9c88e1f86b38eb2b977b1)
@@ -104,5 +104,5 @@
 			Type *replaceWithConcrete( ApplicationExpr *appExpr, Type *type, bool doClone = true );
 			/// wraps a function application returning a polymorphic type with a new temporary for the out-parameter return value
-			Expression *addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *polyType, std::list< Expression *>::iterator &arg );
+			Expression *addDynRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *polyType, std::list< Expression *>::iterator &arg );
 			Expression *applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
 			void boxParam( Type *formal, Expression *&arg, const TyVarMap &exprTyVars );
@@ -661,5 +661,5 @@
 				// process polymorphic return value
 				retval = 0;
-				if ( isPolyRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) {
+				if ( isDynRet( functionDecl->get_functionType() ) && functionDecl->get_linkage() == LinkageSpec::Cforall ) {
 					retval = functionDecl->get_functionType()->get_returnVals().front();
 
@@ -868,7 +868,7 @@
 		}
 
-		Expression *Pass1::addPolyRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *polyType, std::list< Expression *>::iterator &arg ) {
+		Expression *Pass1::addDynRetParam( ApplicationExpr *appExpr, FunctionType *function, ReferenceToType *dynType, std::list< Expression *>::iterator &arg ) {
 			assert( env );
-			Type *concrete = replaceWithConcrete( appExpr, polyType );
+			Type *concrete = replaceWithConcrete( appExpr, dynType );
 			// add out-parameter for return value
 			return addRetParam( appExpr, function, concrete, arg );
@@ -877,5 +877,6 @@
 		Expression *Pass1::applyAdapter( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &tyVars ) {
 			Expression *ret = appExpr;
-			if ( ! function->get_returnVals().empty() && isPolyType( function->get_returnVals().front()->get_type(), tyVars ) ) {
+//			if ( ! function->get_returnVals().empty() && isPolyType( function->get_returnVals().front()->get_type(), tyVars ) ) {
+			if ( isDynRet( function, tyVars ) ) {
 				ret = addRetParam( appExpr, function, function->get_returnVals().front()->get_type(), arg );
 			} // if
@@ -968,5 +969,6 @@
 			// actually make the adapter type
 			FunctionType *adapter = adaptee->clone();
-			if ( ! adapter->get_returnVals().empty() && isPolyType( adapter->get_returnVals().front()->get_type(), tyVars ) ) {
+//			if ( ! adapter->get_returnVals().empty() && isPolyType( adapter->get_returnVals().front()->get_type(), tyVars ) ) {
+			if ( isDynRet( adapter, tyVars ) ) {
 				makeRetParm( adapter );
 			} // if
@@ -1030,5 +1032,6 @@
 				addAdapterParams( adapteeApp, arg, param, adapterType->get_parameters().end(), realParam, tyVars );
 				bodyStmt = new ExprStmt( noLabels, adapteeApp );
-			} else if ( isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
+//			} else if ( isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
+			} else if ( isDynType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
 				// return type T
 				if ( (*param)->get_name() == "" ) {
@@ -1277,8 +1280,8 @@
 			TyVarMap exprTyVars( (TypeDecl::Kind)-1 );
 			makeTyVarMap( function, exprTyVars );
-			ReferenceToType *polyRetType = isPolyRet( function );
-
-			if ( polyRetType ) {
-				ret = addPolyRetParam( appExpr, function, polyRetType, arg );
+			ReferenceToType *dynRetType = isDynRet( function, exprTyVars );
+
+			if ( dynRetType ) {
+				ret = addDynRetParam( appExpr, function, dynRetType, arg );
 			} else if ( needsAdapter( function, scopeTyVars ) ) {
 				// std::cerr << "needs adapter: ";
@@ -1290,5 +1293,5 @@
 			arg = appExpr->get_args().begin();
 
-			passTypeVars( appExpr, polyRetType, arg, exprTyVars );
+			passTypeVars( appExpr, dynRetType, arg, exprTyVars );
 			addInferredParams( appExpr, function, arg, exprTyVars );
 
@@ -1577,5 +1580,5 @@
 
 			// move polymorphic return type to parameter list
-			if ( isPolyRet( funcType ) ) {
+			if ( isDynRet( funcType ) ) {
 				DeclarationWithType *ret = funcType->get_returnVals().front();
 				ret->set_type( new PointerType( Type::Qualifiers(), ret->get_type() ) );
@@ -2051,5 +2054,5 @@
 
 			DeclClass *ret = static_cast< DeclClass *>( Mutator::mutate( decl ) );
-			ScrubTyVars::scrub( decl, scopeTyVars );
+			ScrubTyVars::scrubDynamic( decl, scopeTyVars );
 
 			scopeTyVars.endScope();
Index: src/GenPoly/GenPoly.cc
===================================================================
--- src/GenPoly/GenPoly.cc	(revision a2f920fd2c573edb4b70470fe5d94960bd140fed)
+++ src/GenPoly/GenPoly.cc	(revision 3bb195cb021bb5008ad9c88e1f86b38eb2b977b1)
@@ -23,25 +23,4 @@
 
 namespace GenPoly {
-	bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVars ) {
-		if ( ! adaptee->get_returnVals().empty() && isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
-			return true;
-		} // if
-		for ( std::list< DeclarationWithType* >::const_iterator innerArg = adaptee->get_parameters().begin(); innerArg != adaptee->get_parameters().end(); ++innerArg ) {
-			if ( isPolyType( (*innerArg)->get_type(), tyVars ) ) {
-				return true;
-			} // if
-		} // for
-		return false;
-	}
-
-	ReferenceToType *isPolyRet( FunctionType *function ) {
-		if ( ! function->get_returnVals().empty() ) {
-			TyVarMap forallTypes( (TypeDecl::Kind)-1 );
-			makeTyVarMap( function, forallTypes );
-			return (ReferenceToType*)isPolyType( function->get_returnVals().front()->get_type(), forallTypes );
-		} // if
-		return 0;
-	}
-
 	namespace {
 		/// Checks a parameter list for polymorphic parameters; will substitute according to env if present
@@ -64,4 +43,14 @@
 			return false;
 		}
+
+		/// Checks a parameter list for dynamic-layout parameters from tyVars; will substitute according to env if present
+		bool hasDynParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {
+			for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
+				TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
+				assert(paramType && "Aggregate parameters should be type expressions");
+				if ( isDynType( paramType->get_type(), tyVars, env ) ) return true;
+			}
+			return false;
+		}
 	}
 
@@ -101,4 +90,49 @@
 		}
 		return 0;
+	}
+
+	Type *isDynType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
+		type = replaceTypeInst( type, env );
+
+		if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
+			auto var = tyVars.find( typeInst->get_name() );
+			if ( var != tyVars.end() && var->second == TypeDecl::Any ) {
+				return type;
+			}
+		} else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
+			if ( hasDynParams( structType->get_parameters(), tyVars, env ) ) return type;
+		} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
+			if ( hasDynParams( unionType->get_parameters(), tyVars, env ) ) return type;
+		}
+		return 0;
+	}
+
+	ReferenceToType *isDynRet( FunctionType *function, const TyVarMap &forallTypes ) {
+		if ( function->get_returnVals().empty() ) return 0;
+		
+		return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes );
+	}
+
+	ReferenceToType *isDynRet( FunctionType *function ) {
+		if ( function->get_returnVals().empty() ) return 0;
+
+		TyVarMap forallTypes( (TypeDecl::Kind)-1 );
+		makeTyVarMap( function, forallTypes );
+		return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes );
+	}
+
+	bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVars ) {
+// 		if ( ! adaptee->get_returnVals().empty() && isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
+// 			return true;
+// 		} // if
+		if ( isDynRet( adaptee, tyVars ) ) return true;
+		
+		for ( std::list< DeclarationWithType* >::const_iterator innerArg = adaptee->get_parameters().begin(); innerArg != adaptee->get_parameters().end(); ++innerArg ) {
+// 			if ( isPolyType( (*innerArg)->get_type(), tyVars ) ) {
+			if ( isDynType( (*innerArg)->get_type(), tyVars ) ) {
+				return true;
+			} // if
+		} // for
+		return false;
 	}
 
Index: src/GenPoly/GenPoly.h
===================================================================
--- src/GenPoly/GenPoly.h	(revision a2f920fd2c573edb4b70470fe5d94960bd140fed)
+++ src/GenPoly/GenPoly.h	(revision 3bb195cb021bb5008ad9c88e1f86b38eb2b977b1)
@@ -31,11 +31,4 @@
 namespace GenPoly {
 	typedef ErasableScopedMap< std::string, TypeDecl::Kind > TyVarMap;
-	
-	/// A function needs an adapter if it returns a polymorphic value or if any of its
-	/// parameters have polymorphic type
-	bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVarr );
-
-	/// true iff function has polymorphic return type
-	ReferenceToType *isPolyRet( FunctionType *function );
 
 	/// Replaces a TypeInstType by its referrent in the environment, if applicable
@@ -47,4 +40,16 @@
 	/// returns polymorphic type if is polymorphic type in tyVars, NULL otherwise; will look up substitution in env if provided
 	Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
+
+	/// returns dynamic-layout type if is dynamic-layout type in tyVars, NULL otherwise; will look up substitution in env if provided
+	Type *isDynType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
+
+	/// true iff function has dynamic-layout return type under the given type variable map
+	ReferenceToType *isDynRet( FunctionType *function, const TyVarMap &tyVars );
+
+	/// true iff function has dynamic-layout return type under the type variable map generated from its forall-parameters
+	ReferenceToType *isDynRet( FunctionType *function );
+
+	/// A function needs an adapter if it returns a dynamic-layout value or if any of its parameters have dynamic-layout type
+	bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVarr );
 
 	/// returns polymorphic type if is pointer to polymorphic type, NULL otherwise; will look up substitution in env if provided
Index: src/GenPoly/InstantiateGeneric.cc
===================================================================
--- src/GenPoly/InstantiateGeneric.cc	(revision a2f920fd2c573edb4b70470fe5d94960bd140fed)
+++ src/GenPoly/InstantiateGeneric.cc	(revision 3bb195cb021bb5008ad9c88e1f86b38eb2b977b1)
@@ -24,4 +24,5 @@
 #include "GenPoly.h"
 #include "ScopedMap.h"
+#include "ScopedSet.h"
 
 #include "ResolvExpr/typeops.h"
@@ -122,4 +123,26 @@
 		}
 	};
+
+	/// Possible options for a given specialization of a generic type
+	enum class genericType {
+		dtypeStatic,  ///< Concrete instantiation based solely on {d,f}type-to-void conversions
+		concrete,     ///< Concrete instantiation requiring at least one parameter type
+		dynamic       ///< No concrete instantiation
+	};
+
+	genericType& operator |= ( genericType& gt, const genericType& ht ) {
+		switch ( gt ) {
+		case genericType::dtypeStatic:
+			gt = ht;
+			break;
+		case genericType::concrete:
+			if ( ht == genericType::dynamic ) { gt = genericType::dynamic; }
+			break;
+		case genericType::dynamic:
+			// nothing possible
+			break;
+		}
+		return gt;
+	}
 	
 	/// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
@@ -127,9 +150,11 @@
 		/// Map of (generic type, parameter list) pairs to concrete type instantiations
 		InstantiationMap< AggregateDecl, AggregateDecl > instantiations;
+		/// Set of types which are dtype-only generic (and therefore have static layout)
+		ScopedSet< AggregateDecl* > dtypeStatics;
 		/// Namer for concrete types
 		UniqueName typeNamer;
 
 	public:
-		GenericInstantiator() : DeclMutator(), instantiations(), typeNamer("_conc_") {}
+		GenericInstantiator() : DeclMutator(), instantiations(), dtypeStatics(), typeNamer("_conc_") {}
 
 		virtual Type* mutate( StructInstType *inst );
@@ -147,4 +172,10 @@
 		/// Wrap instantiation insertion for unions
 		void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { instantiations.insert( inst->get_baseUnion(), typeSubs, decl ); }
+
+		/// If this is an instance of a type already determined to be dtype-static, strips the instances's type parameters and returns true
+		bool stripInstParams( AggregateDecl *base, ReferenceToType *inst );
+	
+		/// Strips a dtype-static aggregate decl of its type parameters, marks it as stripped
+		void stripDtypeParams( AggregateDecl *base, std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs );
 	};
 
@@ -154,29 +185,6 @@
 	}
 
-	//////////////////////////////////////// GenericInstantiator //////////////////////////////////////////////////
-
-	/// Possible options for a given specialization of a generic type
-	enum class genericType {
-		dtypeStatic,  ///< Concrete instantiation based solely on {d,f}type-to-void conversions
-		concrete,     ///< Concrete instantiation requiring at least one parameter type
-		dynamic       ///< No concrete instantiation
-	};
-
-	genericType& operator |= ( genericType& gt, const genericType& ht ) {
-		switch ( gt ) {
-		case genericType::dtypeStatic:
-			gt = ht;
-			break;
-		case genericType::concrete:
-			if ( ht == genericType::dynamic ) { gt = genericType::dynamic; }
-			break;
-		case genericType::dynamic:
-			// nothing possible
-			break;
-		}
-		return gt;
-	}
-
-	/// Makes substitutions of params into baseParams; returns true if all parameters substituted for a concrete type
+	/// Makes substitutions of params into baseParams; returns dtypeStatic if there is a concrete instantiation based only on {d,f}type-to-void conversions,
+	/// concrete if there is a concrete instantiation requiring at least one parameter type, and dynamic if there is no concrete instantiation
 	genericType makeSubstitutions( const std::list< TypeDecl* >& baseParams, const std::list< Expression* >& params, std::list< TypeExpr* >& out ) {
 		genericType gt = genericType::dtypeStatic;
@@ -223,4 +231,31 @@
 	}
 
+	/// Substitutes types of members according to baseParams => typeSubs, working in-place
+	void substituteMembers( std::list< Declaration* >& members, const std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs ) {
+		// substitute types into new members
+		TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
+		for ( std::list< Declaration* >::iterator member = members.begin(); member != members.end(); ++member ) {
+			subs.apply(*member);
+		}
+	}
+
+	bool GenericInstantiator::stripInstParams( AggregateDecl *base, ReferenceToType *inst ) {
+		if ( dtypeStatics.find( base ) == dtypeStatics.end() ) return false;
+
+		deleteAll( inst->get_parameters() );
+		inst->get_parameters().clear();
+
+		return true;
+	}
+	
+	void GenericInstantiator::stripDtypeParams( AggregateDecl *base, std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs ) {
+		substituteMembers( base->get_members(), baseParams, typeSubs );
+
+		deleteAll( baseParams );
+		baseParams.clear();
+		
+		dtypeStatics.insert( base );
+	}
+
 	Type* GenericInstantiator::mutate( StructInstType *inst ) {
 		// mutate subtypes
@@ -231,13 +266,18 @@
 		// exit early if no need for further mutation
 		if ( inst->get_parameters().empty() ) return inst;
+
+		// check for an already-instantiatiated dtype-static type
+		if ( stripInstParams( inst->get_baseStruct(), inst ) ) return inst;
+		
+		// check if type can be concretely instantiated; put substitutions into typeSubs
 		assert( inst->get_baseParameters() && "Base struct has parameters" );
-
-		// check if type can be concretely instantiated; put substitutions into typeSubs
 		std::list< TypeExpr* > typeSubs;
 		genericType gt = makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs );
 		switch ( gt ) {
-		case genericType::dtypeStatic: // TODO strip params off original decl and reuse here
-		case genericType::concrete:
-		{
+		case genericType::dtypeStatic:
+			stripDtypeParams( inst->get_baseStruct(), *inst->get_baseParameters(), typeSubs );
+			break;
+		
+		case genericType::concrete: {
 			// make concrete instantiation of generic type
 			StructDecl *concDecl = lookup( inst, typeSubs );
@@ -274,11 +314,17 @@
 		// exit early if no need for further mutation
 		if ( inst->get_parameters().empty() ) return inst;
+
+		// check for an already-instantiatiated dtype-static type
+		if ( stripInstParams( inst->get_baseUnion(), inst ) ) return inst;
+
+		// check if type can be concretely instantiated; put substitutions into typeSubs
 		assert( inst->get_baseParameters() && "Base union has parameters" );
-
-		// check if type can be concretely instantiated; put substitutions into typeSubs
 		std::list< TypeExpr* > typeSubs;
 		genericType gt = makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs );
 		switch ( gt ) {
-		case genericType::dtypeStatic:  // TODO strip params off original decls and reuse here
+		case genericType::dtypeStatic:
+			stripDtypeParams( inst->get_baseUnion(), *inst->get_baseParameters(), typeSubs );
+			break;
+			
 		case genericType::concrete:
 		{
@@ -311,4 +357,5 @@
 		DeclMutator::doBeginScope();
 		instantiations.beginScope();
+		dtypeStatics.beginScope();
 	}
 
@@ -316,4 +363,5 @@
 		DeclMutator::doEndScope();
 		instantiations.endScope();
+		dtypeStatics.endScope();
 	}
 
Index: src/GenPoly/ScrubTyVars.cc
===================================================================
--- src/GenPoly/ScrubTyVars.cc	(revision a2f920fd2c573edb4b70470fe5d94960bd140fed)
+++ src/GenPoly/ScrubTyVars.cc	(revision 3bb195cb021bb5008ad9c88e1f86b38eb2b977b1)
@@ -45,5 +45,5 @@
 
 	Type * ScrubTyVars::mutateAggregateType( Type *ty ) {
-		if ( isPolyType( ty, tyVars ) ) {
+		if ( shouldScrub( ty ) ) {
 			PointerType *ret = new PointerType( Type::Qualifiers(), new VoidType( ty->get_qualifiers() ) );
 			delete ty;
@@ -63,6 +63,6 @@
 	Expression * ScrubTyVars::mutate( SizeofExpr *szeof ) {
 		// sizeof( T ) => _sizeof_T parameter, which is the size of T
-		if ( Type *polyType = isPolyType( szeof->get_type() ) ) {
-			Expression *expr = new NameExpr( sizeofName( mangleType( polyType ) ) );
+		if ( Type *dynType = shouldScrub( szeof->get_type() ) ) {
+			Expression *expr = new NameExpr( sizeofName( mangleType( dynType ) ) );
 			return expr;
 		} else {
@@ -73,6 +73,6 @@
 	Expression * ScrubTyVars::mutate( AlignofExpr *algnof ) {
 		// alignof( T ) => _alignof_T parameter, which is the alignment of T
-		if ( Type *polyType = isPolyType( algnof->get_type() ) ) {
-			Expression *expr = new NameExpr( alignofName( mangleType( polyType ) ) );
+		if ( Type *dynType = shouldScrub( algnof->get_type() ) ) {
+			Expression *expr = new NameExpr( alignofName( mangleType( dynType ) ) );
 			return expr;
 		} else {
@@ -82,6 +82,19 @@
 
 	Type * ScrubTyVars::mutate( PointerType *pointer ) {
-		if ( Type *polyType = isPolyType( pointer->get_base(), tyVars ) ) {
-			Type *ret = polyType->acceptMutator( *this );
+//		// special case of shouldScrub that takes all TypeInstType pointer bases, even if they're not dynamic
+// 		Type *base = pointer->get_base();
+// 		Type *dynType = 0;
+// 		if ( dynamicOnly ) {
+// 			if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( base ) ) {
+// 				if ( tyVars.find( typeInst->get_name() ) != tyVars.end() ) { dynType = typeInst; }
+// 			} else {
+// 				dynType = isDynType( base, tyVars );
+// 			}
+// 		} else {
+// 			dynType = isPolyType( base, tyVars );
+// 		}
+// 		if ( dynType ) {
+		if ( Type *dynType = shouldScrub( pointer->get_base() ) ) {
+			Type *ret = dynType->acceptMutator( *this );
 			ret->get_qualifiers() += pointer->get_qualifiers();
 			pointer->set_base( 0 );
Index: src/GenPoly/ScrubTyVars.h
===================================================================
--- src/GenPoly/ScrubTyVars.h	(revision a2f920fd2c573edb4b70470fe5d94960bd140fed)
+++ src/GenPoly/ScrubTyVars.h	(revision 3bb195cb021bb5008ad9c88e1f86b38eb2b977b1)
@@ -27,5 +27,5 @@
 	class ScrubTyVars : public Mutator {
 	  public:
-		ScrubTyVars( const TyVarMap &tyVars ): tyVars( tyVars ) {}
+		ScrubTyVars( const TyVarMap &tyVars, bool dynamicOnly = false ): tyVars( tyVars ), dynamicOnly( dynamicOnly ) {}
 
 		/// For all polymorphic types with type variables in `tyVars`, replaces generic types, dtypes, and ftypes with the appropriate void type,
@@ -33,4 +33,9 @@
 		template< typename SynTreeClass >
 		static SynTreeClass *scrub( SynTreeClass *target, const TyVarMap &tyVars );
+
+		/// For all dynamic-layout types with type variables in `tyVars`, replaces generic types, dtypes, and ftypes with the appropriate void type,
+		/// and sizeof/alignof expressions with the proper variable
+		template< typename SynTreeClass >
+		static SynTreeClass *scrubDynamic( SynTreeClass *target, const TyVarMap &tyVars );
 
 		virtual Type* mutate( TypeInstType *typeInst );
@@ -42,14 +47,32 @@
 
 	  private:
+		/// Returns the type if it should be scrubbed, NULL otherwise.
+		Type* shouldScrub( Type *ty ) {
+			return dynamicOnly ? isDynType( ty, tyVars ) : isPolyType( ty, tyVars );
+// 			if ( ! dynamicOnly ) return isPolyType( ty, tyVars );
+// 
+// 			if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( ty ) ) {
+// 				return tyVars.find( typeInst->get_name() ) != tyVars.end() ? ty : 0;
+// 			}
+// 
+// 			return isDynType( ty, tyVars );
+		}
+		
 		/// Mutates (possibly generic) aggregate types appropriately
 		Type* mutateAggregateType( Type *ty );
 		
-		const TyVarMap &tyVars;
+		const TyVarMap &tyVars;  ///< Type variables to scrub
+		bool dynamicOnly;        ///< only scrub the types with dynamic layout? [false]
 	};
 
-	/* static class method */
 	template< typename SynTreeClass >
 	SynTreeClass * ScrubTyVars::scrub( SynTreeClass *target, const TyVarMap &tyVars ) {
 		ScrubTyVars scrubber( tyVars );
+		return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );
+	}
+
+	template< typename SynTreeClass >
+	SynTreeClass * ScrubTyVars::scrubDynamic( SynTreeClass *target, const TyVarMap &tyVars ) {
+		ScrubTyVars scrubber( tyVars, true );
 		return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );
 	}
Index: src/SymTab/Autogen.cc
===================================================================
--- src/SymTab/Autogen.cc	(revision a2f920fd2c573edb4b70470fe5d94960bd140fed)
+++ src/SymTab/Autogen.cc	(revision 3bb195cb021bb5008ad9c88e1f86b38eb2b977b1)
@@ -174,7 +174,7 @@
 
 	void makeStructMemberOp( ObjectDecl * dstParam, Expression * src, DeclarationWithType * field, FunctionDecl * func, TypeSubstitution & genericSubs, bool isDynamicLayout, bool forward = true ) {
-		if ( isDynamicLayout && src ) {
-			genericSubs.apply( src );
-		}
+// 		if ( isDynamicLayout && src ) {
+// 			genericSubs.apply( src );
+// 		}
 
 		ObjectDecl * returnVal = NULL;
