Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 1ced8743007d42f02646265a58b18e7ee8b8fba5)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision e76acbe263981fcec0d63a2dfbeb9dd2682ae120)
@@ -174,4 +174,16 @@
 			}
 		}
+
+		// flatten tuple type into list of types
+		template< typename OutputIterator >
+		void flatten( Type * type, OutputIterator out ) {
+			if ( TupleType * tupleType = dynamic_cast< TupleType * >( type ) ) {
+				for ( Type * t : *tupleType ) {
+					flatten( t, out );
+				}
+			} else {
+				*out++ = type;
+			}
+		}
 	}
 
@@ -269,5 +281,9 @@
 		std::list< Expression* >& actuals = appExpr->get_args();
 
+		std::list< Type * > formalTypes;
+		std::list< Type * >::iterator formalType = formalTypes.end();
+
 		for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
+
 			PRINT(
 				std::cerr << "actual expression:" << std::endl;
@@ -279,13 +295,25 @@
 			Cost actualCost;
 			for ( std::list< Type* >::iterator actualType = (*actualExpr)->get_results().begin(); actualType != (*actualExpr)->get_results().end(); ++actualType ) {
-				// xxx - need tuple handling code here
-				if ( formal == formals.end() ) {
-					if ( function->get_isVarArgs() ) {
-						convCost += Cost( 1, 0, 0 );
-						break;
-					} else {
-						return Cost::infinity;
+
+				// tuple handling code
+				if ( formalType == formalTypes.end() ) {
+					// the type of the formal parameter may be a tuple type. To make this easier to work with,
+					// flatten the tuple type and traverse the resulting list of types, incrementing the formal
+					// iterator once its types have been extracted. Once a particular formal parameter's type has
+					// been exhausted load the next formal parameter's type.
+					if ( formal == formals.end() ) {
+						if ( function->get_isVarArgs() ) {
+							convCost += Cost( 1, 0, 0 );
+							break;
+						} else {
+							return Cost::infinity;
+						}
 					}
+					formalTypes.clear();
+					flatten( (*formal)->get_type(), back_inserter( formalTypes ) );
+					formalType = formalTypes.begin();
+					++formal;
 				}
+
 				PRINT(
 					std::cerr << std::endl << "converting ";
@@ -294,5 +322,5 @@
 					(*formal)->get_type()->print( std::cerr, 8 );
 				)
-				Cost newCost = conversionCost( *actualType, (*formal)->get_type(), indexer, alt.env );
+				Cost newCost = conversionCost( *actualType, *formalType, indexer, alt.env );
 				PRINT(
 					std::cerr << std::endl << "cost is" << newCost << std::endl;
@@ -305,7 +333,7 @@
 				actualCost += newCost;
 
-				convCost += Cost( 0, polyCost( (*formal)->get_type(), alt.env, indexer ) + polyCost( *actualType, alt.env, indexer ), 0 );
-
-				formal++;
+				convCost += Cost( 0, polyCost( *formalType, alt.env, indexer ) + polyCost( *actualType, alt.env, indexer ), 0 );
+
+				formalType++;
 			}
 			if ( actualCost != Cost( 0, 0, 0 ) ) {
@@ -362,15 +390,4 @@
 			}
 ///     needAssertions.insert( needAssertions.end(), (*tyvar)->get_assertions().begin(), (*tyvar)->get_assertions().end() );
-		}
-	}
-
-	template< typename OutputIterator >
-	void flatten( Type * type, OutputIterator out ) {
-		if ( TupleType * tupleType = dynamic_cast< TupleType * >( type ) ) {
-			for ( Type * t : *tupleType ) {
-				flatten( t, out );
-			}
-		} else {
-			*out++ = type;
 		}
 	}
