Index: src/GenPoly/Box.cc
===================================================================
--- src/GenPoly/Box.cc	(revision bed4d37ced0432647ca13a9e766257d80ac0d9d6)
+++ src/GenPoly/Box.cc	(revision 5c52b06f5452e4062363f7830a32272f9136cfbc)
@@ -73,6 +73,8 @@
 			/// Makes a new temporary array holding the offsets of the fields of `type`, and returns a new variable expression referencing it
 			Expression *makeOffsetArray( StructInstType *type );
+			/// Pass the extra type parameters from polymorphic generic arguments or return types into a function application
+			void passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes );
 			/// passes extra type parameters into a polymorphic function application
-			void passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
+			void passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars );
 			/// wraps a function application with a new temporary for the out-parameter return value
 			Expression *addRetParam( ApplicationExpr *appExpr, FunctionType *function, Type *retType, std::list< Expression *>::iterator &arg );
@@ -398,5 +400,28 @@
 		}
 
-		void Pass1::passTypeVars( ApplicationExpr *appExpr, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
+		void Pass1::passArgTypeVars( ApplicationExpr *appExpr, Type *parmType, Type *argBaseType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars, std::set< std::string > &seenTypes ) {
+			Type *polyBase = hasPolyBase( parmType, exprTyVars );
+			if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
+				std::string sizeName = sizeofName( polyBase );
+				if ( seenTypes.count( sizeName ) ) return;
+
+				arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) );
+				arg++;
+				arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) );
+				arg++;
+				if ( dynamic_cast< StructInstType* >( polyBase ) ) {
+					if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) {
+						arg = appExpr->get_args().insert( arg, makeOffsetArray( argBaseStructType ) );
+						arg++;
+					} else {
+						throw SemanticError( "Cannot pass non-struct type for generic struct" );
+					}
+				}
+
+				seenTypes.insert( sizeName );
+			}
+		}
+
+		void Pass1::passTypeVars( ApplicationExpr *appExpr, ReferenceToType *polyRetType, std::list< Expression *>::iterator &arg, const TyVarMap &exprTyVars ) {
 			// pass size/align for type variables
 			for ( TyVarMap::const_iterator tyParm = exprTyVars.begin(); tyParm != exprTyVars.end(); ++tyParm ) {
@@ -424,28 +449,16 @@
 			std::list< Expression* >::const_iterator fnArg = arg;
 			std::set< std::string > seenTypes; //< names for generic types we've seen
+
+			// a polymorphic return type may need to be added to the argument list
+			if ( polyRetType ) {
+				Type *concRetType = replaceWithConcrete( appExpr, polyRetType );
+				passArgTypeVars( appExpr, polyRetType, concRetType, arg, exprTyVars, seenTypes );
+			}
+			
+			// add type information args for presently unseen types in parameter list
 			for ( ; fnParm != funcType->get_parameters().end() && fnArg != appExpr->get_args().end(); ++fnParm, ++fnArg ) {
-				Type *polyBase = hasPolyBase( (*fnParm)->get_type(), exprTyVars );
-				if ( polyBase && ! dynamic_cast< TypeInstType* >( polyBase ) ) {
-					std::string sizeName = sizeofName( polyBase );
-					if ( seenTypes.count( sizeName ) ) continue;
-
-					VariableExpr *fnArgBase = getBaseVar( *fnArg );
-					assert( fnArgBase && ! fnArgBase->get_results().empty() );
-					Type *argBaseType = fnArgBase->get_results().front();
-					arg = appExpr->get_args().insert( arg, new SizeofExpr( argBaseType->clone() ) );
-					arg++;
-					arg = appExpr->get_args().insert( arg, new AlignofExpr( argBaseType->clone() ) );
-					arg++;
-					if ( dynamic_cast< StructInstType* >( polyBase ) ) {
-						if ( StructInstType *argBaseStructType = dynamic_cast< StructInstType* >( argBaseType ) ) {
-							arg = appExpr->get_args().insert( arg, makeOffsetArray( argBaseStructType ) );
-							arg++;
-						} else {
-							throw SemanticError( "Cannot pass non-struct type for generic struct" );
-						}
-					}
-
-					seenTypes.insert( sizeName );
-				}
+				VariableExpr *fnArgBase = getBaseVar( *fnArg );
+				if ( ! fnArgBase || fnArgBase->get_results().empty() ) continue;
+				passArgTypeVars( appExpr, (*fnParm)->get_type(), fnArgBase->get_results().front(), arg, exprTyVars, seenTypes );
 			}
 		}
@@ -470,6 +483,7 @@
 			ObjectDecl *newObj = makeTemporary( retType->clone() );
 			Expression *paramExpr = new VariableExpr( newObj );
-			// If the type of the temporary is not polymorphic, box temporary by taking its address; otherwise the
-			// temporary is already boxed and can be used directly.
+
+			// If the type of the temporary is not polymorphic, box temporary by taking its address;
+			// otherwise the temporary is already boxed and can be used directly.
 			if ( ! isPolyType( newObj->get_type(), scopeTyVars, env ) ) {
 				paramExpr = new AddressExpr( paramExpr );
@@ -520,4 +534,5 @@
 			assert( env );
 			Type *concrete = replaceWithConcrete( appExpr, polyType );
+			// add out-parameter for return value	
 			return addRetParam( appExpr, function, concrete, arg );
 		}
@@ -917,6 +932,10 @@
 			std::list< Expression *>::iterator paramBegin = appExpr->get_args().begin();
 
-			if ( ReferenceToType *polyType = isPolyRet( function ) ) {
-				ret = addPolyRetParam( appExpr, function, polyType, arg );
+			TyVarMap exprTyVars;
+			makeTyVarMap( function, exprTyVars );
+			ReferenceToType *polyRetType = 0;
+
+			if ( polyRetType = isPolyRet( function ) ) {
+				ret = addPolyRetParam( appExpr, function, polyRetType, arg );
 			} else if ( needsAdapter( function, scopeTyVars ) ) {
 				// std::cerr << "needs adapter: ";
@@ -930,8 +949,5 @@
 			arg = appExpr->get_args().begin();
 
-			TyVarMap exprTyVars;
-			makeTyVarMap( function, exprTyVars );
-
-			passTypeVars( appExpr, arg, exprTyVars );
+			passTypeVars( appExpr, polyRetType, arg, exprTyVars );
 			addInferredParams( appExpr, function, arg, exprTyVars );
 
@@ -1229,5 +1245,5 @@
 			}
 
-			// add size/align for generic types to parameter list
+			// add size/align for generic parameter types to parameter list
 			std::set< std::string > seenTypes; // sizeofName for generic types we've seen
 			for ( std::list< DeclarationWithType* >::const_iterator fnParm = last; fnParm != funcType->get_parameters().end(); ++fnParm ) {
@@ -1429,5 +1445,5 @@
 				delete offsetofExpr;
 				return offsetInd;
-			} else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( ty ) ) {
+			} else if ( dynamic_cast< UnionInstType* >( ty ) ) {
 				// all union members are at offset zero
 				delete offsetofExpr;
