Index: src/Tuples/TupleExpansion.cc
===================================================================
--- src/Tuples/TupleExpansion.cc	(revision acd7c5dd143dff5c52de066e47bcb0c79b405bf2)
+++ src/Tuples/TupleExpansion.cc	(revision c92c09c3c8670e9a320f63ffae0dfeaa24c6c14d)
@@ -66,16 +66,9 @@
 		};
 
-		class TupleTypeReplacer : public GenPoly::DeclMutator {
-		  public:
-			typedef GenPoly::DeclMutator Parent;
-			using Parent::mutate;
-
-			virtual Type * mutate( TupleType * tupleType ) override;
-
-			virtual CompoundStmt * mutate( CompoundStmt * stmt ) override {
-				typeMap.beginScope();
-				stmt = Parent::mutate( stmt );
-				typeMap.endScope();
-				return stmt;
+		struct TupleTypeReplacer : public WithDeclsToAdd, public WithGuards, public WithTypeSubstitution {
+			Type * postmutate( TupleType * tupleType );
+
+			void premutate( CompoundStmt * ) {
+				GuardScope( typeMap );
 			}
 		  private:
@@ -111,6 +104,6 @@
 		mutateAll( translationUnit, assnExpander );
 
-		TupleTypeReplacer replacer;
-		replacer.mutateDeclarationList( translationUnit );
+		PassVisitor<TupleTypeReplacer> replacer;
+		mutateAll( translationUnit, replacer );
 
 		PassVisitor<TupleIndexExpander> idxExpander;
@@ -218,6 +211,5 @@
 	}
 
-	Type * TupleTypeReplacer::mutate( TupleType * tupleType ) {
-		tupleType = safe_dynamic_cast< TupleType * > ( Parent::mutate( tupleType ) );
+	Type * TupleTypeReplacer::postmutate( TupleType * tupleType ) {
 		unsigned tupleSize = tupleType->size();
 		if ( ! typeMap.count( tupleSize ) ) {
@@ -226,5 +218,5 @@
 			decl->set_body( true );
 			for ( size_t i = 0; i < tupleSize; ++i ) {
-				TypeDecl * tyParam = new TypeDecl( toString( "tuple_param_", i ), Type::StorageClasses(), nullptr, TypeDecl::Any );
+				TypeDecl * tyParam = new TypeDecl( toString( "tuple_param_", tupleSize, "_", i ), Type::StorageClasses(), nullptr, TypeDecl::Any );
 				decl->get_members().push_back( new ObjectDecl( toString("field_", i ), Type::StorageClasses(), LinkageSpec::C, nullptr, new TypeInstType( Type::Qualifiers(), tyParam->get_name(), tyParam ), nullptr ) );
 				decl->get_parameters().push_back( tyParam );
@@ -235,5 +227,5 @@
 			}
 			typeMap[tupleSize] = decl;
-			addDeclaration( decl );
+			declsToAddBefore.push_back( decl );
 		}
 		Type::Qualifiers qualifiers = tupleType->get_qualifiers();
@@ -241,6 +233,13 @@
 		StructDecl * decl = typeMap[tupleSize];
 		StructInstType * newType = new StructInstType( qualifiers, decl );
-		for ( Type * t : *tupleType ) {
+		for ( auto p : group_iterate( tupleType->get_types(), decl->get_parameters() ) ) {
+			Type * t = std::get<0>(p);
+			TypeDecl * td = std::get<1>(p);
 			newType->get_parameters().push_back( new TypeExpr( t->clone() ) );
+			if ( env ) {
+				// add bindings to the type environment.
+				// xxx - This may not be sufficient, it may be necessary to rename type variables on StructInstType?
+				env->add( td->get_name(), t->clone() );
+			}
 		}
 		delete tupleType;
