Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision 4c8621ac0673e269714072f2f0e355df9f6462de)
+++ src/GenPoly/Box.cc	(revision 6c3a988fe7dbaec419f8cc1c6be3085432447a99)
@@ -783,5 +783,5 @@
 		void Pass1::boxParams( ApplicationExpr *appExpr, FunctionType *function, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
 			for ( std::list< DeclarationWithType *>::const_iterator param = function->get_parameters().begin(); param != function->get_parameters().end(); ++param, ++arg ) {
-				assert( arg != appExpr->get_args().end() );
+				assertf( arg != appExpr->get_args().end(), "boxParams: missing argument for param %s to %s in %s", toString( *param ).c_str(), toString( function ).c_str(), toString( appExpr ).c_str() );
 				addCast( *arg, (*param)->get_type(), exprTyVars );
 				boxParam( (*param)->get_type(), *arg, exprTyVars );
Index: src/GenPoly/Specialize.cc
===================================================================
--- src/GenPoly/Specialize.cc	(revision 4c8621ac0673e269714072f2f0e355df9f6462de)
+++ src/GenPoly/Specialize.cc	(revision 6c3a988fe7dbaec419f8cc1c6be3085432447a99)
@@ -112,8 +112,7 @@
 		FunctionType *newType = funType->clone();
 		if ( env ) {
-			TypeSubstitution newEnv( *env );
 			// it is important to replace only occurrences of type variables that occur free in the
 			// thunk's type
-			newEnv.applyFree( newType );
+			env->applyFree( newType );
 		} // if
 		// create new thunk with same signature as formal type (C linkage, empty body)
@@ -167,6 +166,5 @@
 		assertf( actual->has_result(), "attempting to specialize an untyped expression" );
 		if ( needsSpecialization( formalType, actual->get_result(), env ) ) {
-			FunctionType *funType;
-			if ( ( funType = getFunctionType( formalType ) ) ) {
+			if ( FunctionType *funType = getFunctionType( formalType ) ) {
 				ApplicationExpr *appExpr;
 				VariableExpr *varExpr;
@@ -188,5 +186,4 @@
 
 	bool TupleSpecializer::needsSpecialization( Type *formalType, Type *actualType, TypeSubstitution *env ) {
-		// std::cerr << "asking if type needs tuple spec: " << formalType << std::endl;
 		if ( FunctionType * ftype = getFunctionType( formalType ) ) {
 			return ftype->isTtype();
@@ -215,5 +212,5 @@
 	void fixLastArg( Expression * last, Iterator begin, Iterator end, OutIterator out ) {
 		// safe_dynamic_cast for the assertion
-		safe_dynamic_cast< TupleType * >( last->get_result() ); // xxx - it's quite possible this will trigger for the unary case...
+		safe_dynamic_cast< TupleType * >( last->get_result() );
 		unsigned idx = 0;
 		for ( ; begin != end; ++begin ) {
@@ -227,12 +224,10 @@
 	Expression * TupleSpecializer::createThunkFunction( FunctionType *funType, Expression *actual, InferredParams *inferParams ) {
 		static UniqueName thunkNamer( "_tupleThunk" );
-		// std::cerr << "creating tuple thunk for " << funType << std::endl;
 
 		FunctionType *newType = funType->clone();
 		if ( env ) {
-			TypeSubstitution newEnv( *env );
 			// it is important to replace only occurrences of type variables that occur free in the
 			// thunk's type
-			newEnv.applyFree( newType );
+			env->applyFree( newType );
 		} // if
 		// create new thunk with same signature as formal type (C linkage, empty body)
@@ -246,7 +241,11 @@
 		UniqueName paramNamer( paramPrefix );
 		ApplicationExpr *appExpr = new ApplicationExpr( actual );
-		// std::cerr << actual << std::endl;
-
-		FunctionType * actualType = getFunctionType( actual->get_result() );
+
+		FunctionType * actualType = getFunctionType( actual->get_result() )->clone();
+		if ( env ) {
+			// need to apply the environment to the actual function's type, since it may itself be polymorphic
+			env->apply( actualType );
+		}
+		std::unique_ptr< FunctionType > actualTypeManager( actualType ); // for RAII
 		std::list< DeclarationWithType * >::iterator actualBegin = actualType->get_parameters().begin();
 		std::list< DeclarationWithType * >::iterator actualEnd = actualType->get_parameters().end();
@@ -282,5 +281,5 @@
 		std::list< Statement* > oldStmts;
 		oldStmts.splice( oldStmts.end(), stmtsToAdd );
-		spec.handleExplicitParams( appExpr );
+		spec.mutate( appExpr );
 		paramPrefix = oldParamPrefix;
 		// write any statements added for recursive specializations into the thunk body
@@ -297,6 +296,4 @@
 		} // if
 		thunkFunc->get_statements()->get_kids().push_back( appStmt );
-
-		// std::cerr << "thunkFunc is: " << thunkFunc << std::endl;
 
 		// add thunk definition to queue of statements to add
@@ -326,5 +323,5 @@
 			// don't need to do this for intrinsic calls, because they aren't actually passed
 			for ( InferredParams::iterator inferParam = appExpr->get_inferParams().begin(); inferParam != appExpr->get_inferParams().end(); ++inferParam ) {
-				inferParam->second.expr = specializer->doSpecialization( inferParam->second.formalType, inferParam->second.expr, &appExpr->get_inferParams() );
+				inferParam->second.expr = specializer->doSpecialization( inferParam->second.formalType, inferParam->second.expr, inferParam->second.inferParams.get() );
 			}
 			handleExplicitParams( appExpr );
