Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision fba44f88c0909ebe9f84c63385f6fa1d508208a7)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 0362d42197982e555c473ed139d94d754200a435)
@@ -267,4 +267,5 @@
 		std::list< DeclarationWithType* >::iterator formal = formals.begin();
 		std::list< Expression* >& actuals = appExpr->get_args();
+
 		for ( std::list< Expression* >::iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
 			PRINT(
@@ -276,5 +277,6 @@
 			std::list< DeclarationWithType* >::iterator startFormal = formal;
 			Cost actualCost;
-			for ( std::list< Type* >::iterator actual = (*actualExpr)->get_results().begin(); actual != (*actualExpr)->get_results().end(); ++actual ) {
+			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() ) {
@@ -287,9 +289,9 @@
 				PRINT(
 					std::cerr << std::endl << "converting ";
-					(*actual)->print( std::cerr, 8 );
+					(*actualType)->print( std::cerr, 8 );
 					std::cerr << std::endl << " to ";
 					(*formal)->get_type()->print( std::cerr, 8 );
 				)
-				Cost newCost = conversionCost( *actual, (*formal)->get_type(), indexer, alt.env );
+				Cost newCost = conversionCost( *actualType, (*formal)->get_type(), indexer, alt.env );
 				PRINT(
 					std::cerr << std::endl << "cost is" << newCost << std::endl;
@@ -302,5 +304,5 @@
 				actualCost += newCost;
 
-				convCost += Cost( 0, polyCost( (*formal)->get_type(), alt.env, indexer ) + polyCost( *actual, alt.env, indexer ), 0 );
+				convCost += Cost( 0, polyCost( (*formal)->get_type(), alt.env, indexer ) + polyCost( *actualType, alt.env, indexer ), 0 );
 
 				formal++;
@@ -362,4 +364,15 @@
 	}
 
+	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;
+		}
+	}
+
 	bool AlternativeFinder::instantiateFunction( std::list< DeclarationWithType* >& formals, /*const*/ AltList &actuals, bool isVarArgs, OpenVarSet& openVars, TypeEnvironment &resultEnv, AssertionSet &resultNeed, AssertionSet &resultHave ) {
 		simpleCombineEnvironments( actuals.begin(), actuals.end(), resultEnv );
@@ -379,8 +392,23 @@
 		*/
 		std::list< DeclarationWithType* >::iterator formal = formals.begin();
+
+		std::list< Type * > formalTypes;
+		std::list< Type * >::iterator formalType = formalTypes.end();
+
 		for ( AltList::const_iterator actualExpr = actuals.begin(); actualExpr != actuals.end(); ++actualExpr ) {
-			for ( std::list< Type* >::iterator actual = actualExpr->expr->get_results().begin(); actual != actualExpr->expr->get_results().end(); ++actual ) {
-				if ( formal == formals.end() ) {
-					return isVarArgs;
+			std::list< Type* > & actualTypes = actualExpr->expr->get_results();
+			for ( std::list< Type* >::iterator actualType = actualTypes.begin(); actualType != actualTypes.end(); ++actualType ) {
+				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() ) {
+						return isVarArgs;
+					}
+					formalTypes.clear();
+					flatten( (*formal)->get_type(), back_inserter( formalTypes ) );
+					formalType = formalTypes.begin();
+					++formal;
 				}
 				PRINT(
@@ -388,13 +416,18 @@
 					(*formal)->get_type()->print( std::cerr );
 					std::cerr << std::endl << "actual type is ";
-					(*actual)->print( std::cerr );
+					(*actualType)->print( std::cerr );
 					std::cerr << std::endl;
 				)
-				if ( ! unify( (*formal)->get_type(), *actual, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
+				if ( ! unify( *formalType, *actualType, resultEnv, resultNeed, resultHave, openVars, indexer ) ) {
 					return false;
 				}
-				formal++;
-			}
-		}
+				++formalType;
+			}
+		}
+
+		// xxx - a tuple type was not completely matched
+		// partially handle the tuple with default arguments??
+		if ( formalType != formalTypes.end() ) return false;
+
 		// Handling of default values
 		while ( formal != formals.end() ) {
Index: src/ResolvExpr/AlternativeFinder.h
===================================================================
--- src/ResolvExpr/AlternativeFinder.h	(revision fba44f88c0909ebe9f84c63385f6fa1d508208a7)
+++ src/ResolvExpr/AlternativeFinder.h	(revision 0362d42197982e555c473ed139d94d754200a435)
@@ -67,4 +67,6 @@
 		virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr );
 	  public:  // xxx - temporary hack - should make Tuples::TupleAssignment a friend
+	  /// Runs a new alternative finder on each element in [begin, end)
+	  /// and writes each alternative finder to out.
 		template< typename InputIterator, typename OutputIterator >
 		void findSubExprs( InputIterator begin, InputIterator end, OutputIterator out );
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision fba44f88c0909ebe9f84c63385f6fa1d508208a7)
+++ src/SynTree/Type.h	(revision 0362d42197982e555c473ed139d94d754200a435)
@@ -352,5 +352,11 @@
 	virtual ~TupleType();
 
+	typedef std::list<Type*> value_type;
+	typedef value_type::iterator iterator;
+
 	std::list<Type*>& get_types() { return types; }
+
+	iterator begin() { return types.begin(); }
+	iterator end() { return types.end(); }
 
 	virtual TupleType *clone() const { return new TupleType( *this ); }
