Index: src/GenPoly/BoxNew.cpp
===================================================================
--- src/GenPoly/BoxNew.cpp	(revision 04db9f67a6831b461e75e0c77e20333279541951)
+++ src/GenPoly/BoxNew.cpp	(revision 097c8d0db2c39c0fca0eb36f369aea4b09227342)
@@ -1521,69 +1521,10 @@
 /// * Move polymorphic returns in function types to pointer-type parameters.
 /// * Adds type size and assertion parameters to parameter lists.
-struct DeclAdapter final :
-		public BoxPass,
-		public ast::WithGuards {
-	void handleAggrDecl();
-
-	void previsit( ast::StructDecl const * decl );
-	void previsit( ast::UnionDecl const * decl );
-	void previsit( ast::TraitDecl const * decl );
-	void previsit( ast::TypeDecl const * decl );
-	void previsit( ast::PointerType const * type );
+struct DeclAdapter final {
 	ast::FunctionDecl const * previsit( ast::FunctionDecl const * decl );
 	ast::FunctionDecl const * postvisit( ast::FunctionDecl const * decl );
-	void previsit( ast::CompoundStmt const * stmt );
 private:
-	ast::FunctionDecl * addAdapters( ast::FunctionDecl * decl );
-
-	std::map<UniqueId, std::string> adapterName;
+	void addAdapters( ast::FunctionDecl * decl, TypeVarMap & localTypeVars );
 };
-
-// at must point within [dst.begin(), dst.end()].
-template< typename T >
-void spliceAt( std::vector< T > & dst, typename std::vector< T >::iterator at,
-		std::vector< T > & src ) {
-	std::vector< T > tmp;
-	tmp.reserve( dst.size() + src.size() );
-	typename std::vector< T >::iterator it = dst.begin();
-	while ( it != at ) {
-		assert( it != dst.end() );
-		tmp.emplace_back( std::move( *it ) );
-		++it;
-	}
-	for ( T & x : src ) { tmp.emplace_back( std::move( x ) ); }
-	while ( it != dst.end() ) {
-		tmp.emplace_back( std::move( *it ) );
-		++it;
-	}
-
-	dst.clear();
-	src.clear();
-	tmp.swap( dst );
-}
-
-void DeclAdapter::previsit( ast::StructDecl const * ) {
-	// Prevent type vars from leaking into the containing scope.
-	GuardScope( scopeTypeVars );
-}
-
-void DeclAdapter::previsit( ast::UnionDecl const * ) {
-	// Prevent type vars from leaking into the containing scope.
-	GuardScope( scopeTypeVars );
-}
-
-void DeclAdapter::previsit( ast::TraitDecl const * ) {
-	// Prevent type vars from leaking into the containing scope.
-	GuardScope( scopeTypeVars );
-}
-
-void DeclAdapter::previsit( ast::TypeDecl const * decl ) {
-	addToTypeVarMap( decl, scopeTypeVars );
-}
-
-void DeclAdapter::previsit( ast::PointerType const * type ) {
-	GuardScope( scopeTypeVars );
-	makeTypeVarMap( type, scopeTypeVars );
-}
 
 // size/align/offset parameters may not be used, so add the unused attribute.
@@ -1604,6 +1545,6 @@
 
 ast::FunctionDecl const * DeclAdapter::previsit( ast::FunctionDecl const * decl ) {
-	GuardScope( scopeTypeVars );
-	makeTypeVarMap( decl, scopeTypeVars );
+	TypeVarMap localTypeVars = { ast::TypeData() };
+	makeTypeVarMap( decl, localTypeVars );
 
 	auto mutDecl = mutate( decl );
@@ -1620,6 +1561,6 @@
 
 	// Add size/align and assertions for type parameters to parameter list.
-	ast::vector<ast::DeclWithType>::iterator last = mutDecl->params.begin();
 	ast::vector<ast::DeclWithType> inferredParams;
+	ast::vector<ast::DeclWithType> layoutParams;
 	for ( ast::ptr<ast::TypeDecl> & typeParam : mutDecl->type_params ) {
 		auto mutParam = mutate( typeParam.get() );
@@ -1630,10 +1571,8 @@
 
 			auto sizeParam = makeObj( typeParam->location, sizeofName( paramName ) );
-			last = mutDecl->params.insert( last, sizeParam );
-			++last;
+			layoutParams.emplace_back( sizeParam );
 
 			auto alignParam = makeObj( typeParam->location, alignofName( paramName ) );
-			last = mutDecl->params.insert( last, alignParam );
-			++last;
+			layoutParams.emplace_back( alignParam );
 		}
 		// TODO: These should possibly all be gone.
@@ -1663,5 +1602,5 @@
 	ast::vector<ast::DeclWithType> otypeParams;
 	for ( ast::ptr<ast::DeclWithType> & funcParam : mutDecl->params ) {
-		ast::Type const * polyType = isPolyType( funcParam->get_type(), scopeTypeVars );
+		ast::Type const * polyType = isPolyType( funcParam->get_type(), localTypeVars );
 		if ( !polyType || dynamic_cast<ast::TypeInstType const *>( polyType ) ) {
 			continue;
@@ -1669,4 +1608,5 @@
 		std::string typeName = Mangle::mangleType( polyType );
 		if ( seenTypes.count( typeName ) ) continue;
+		seenTypes.insert( typeName );
 
 		auto sizeParam = makeObj( funcParam->location, sizeofName( typeName ) );
@@ -1676,22 +1616,20 @@
 		otypeParams.emplace_back( alignParam );
 
+		// Zero-length arrays are illegal in C, so empty structs have no
+		// offset array.
 		if ( auto * polyStruct =
-				dynamic_cast<ast::StructInstType const *>( polyType ) ) {
-			// Zero-length arrays are illegal in C, so empty structs have no
-			// offset array.
-			if ( !polyStruct->base->members.empty() ) {
-				auto offsetParam = makePtr( funcParam->location, offsetofName( typeName ) );
-				otypeParams.emplace_back( offsetParam );
-			}
-		}
-		seenTypes.insert( typeName );
-	}
-
-	// TODO: A unified way of putting these together might be nice.
-	// Put the list together: adapters (in helper) otype parameters,
-	// inferred params., layout params. (done) and finally explicit params.
-	spliceBegin( inferredParams, otypeParams );
-	spliceAt( mutDecl->params, last, inferredParams );
-	mutDecl = addAdapters( mutDecl );
+				dynamic_cast<ast::StructInstType const *>( polyType ) ;
+				polyStruct && !polyStruct->base->members.empty() ) {
+			auto offsetParam = makePtr( funcParam->location, offsetofName( typeName ) );
+			otypeParams.emplace_back( offsetParam );
+		}
+	}
+
+	// Prepend each argument group. From last group to first. addAdapters
+	// does do the same, it just does it itself and see all other parameters.
+	spliceBegin( mutDecl->params, inferredParams );
+	spliceBegin( mutDecl->params, otypeParams );
+	spliceBegin( mutDecl->params, layoutParams );
+	addAdapters( mutDecl, localTypeVars );
 
 	return mutDecl;
@@ -1732,28 +1670,15 @@
 }
 
-void DeclAdapter::previsit( ast::CompoundStmt const * ) {
-	GuardScope( scopeTypeVars );
-	// TODO: It is entirely possible the scope doesn't need to spread
-	// across multiple functions. Otherwise, find a better clear.
-	std::set<TypeVarMap::key_type> keys;
-	for ( auto pair : const_cast<TypeVarMap const &>( scopeTypeVars ) ) {
-		keys.insert( pair.first );
-	}
-	for ( auto key : keys ) {
-		scopeTypeVars.erase( key );
-	}
-}
-
-// It actually does mutate in-place, but does the return for consistency.
-ast::FunctionDecl * DeclAdapter::addAdapters( ast::FunctionDecl * mutDecl ) {
+void DeclAdapter::addAdapters(
+		ast::FunctionDecl * mutDecl, TypeVarMap & localTypeVars ) {
 	ast::vector<ast::FunctionType> functions;
 	for ( ast::ptr<ast::DeclWithType> & arg : mutDecl->params ) {
 		ast::Type const * type = arg->get_type();
-		type = findAndReplaceFunction( type, functions, scopeTypeVars, needsAdapter );
+		type = findAndReplaceFunction( type, functions, localTypeVars, needsAdapter );
 		arg.get_and_mutate()->set_type( type );
 	}
 	std::set<std::string> adaptersDone;
 	for ( ast::ptr<ast::FunctionType> const & func : functions ) {
-		std::string mangleName = mangleAdapterName( func, scopeTypeVars );
+		std::string mangleName = mangleAdapterName( func, localTypeVars );
 		if ( adaptersDone.find( mangleName ) != adaptersDone.end() ) {
 			continue;
@@ -1763,10 +1688,9 @@
 		mutDecl->params.insert( mutDecl->params.begin(), new ast::ObjectDecl(
 			mutDecl->location, adapterName,
-			new ast::PointerType( makeAdapterType( func, scopeTypeVars ) ),
+			new ast::PointerType( makeAdapterType( func, localTypeVars ) ),
 			nullptr, {}, {}, nullptr,
 			{ new ast::Attribute( "unused" ) } ) );
 		adaptersDone.insert( adaptersDone.begin(), mangleName );
 	}
-	return mutDecl;
 }
 
