Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision fc638d2176b72a88b406e73af7f7f9e548ae05f7)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 793335167c5347f27e76d8ab9f3434b795a6602d)
@@ -185,5 +185,5 @@
 			if ( alternatives.begin() == oldBegin ) {
 				std::ostringstream stream;
-				stream << "Can't choose between alternatives for expression ";
+				stream << "Can't choose between " << alternatives.size() << " alternatives for expression ";
 				expr->print( stream );
 				stream << "Alternatives are:";
@@ -308,5 +308,5 @@
 					(*actualType)->print( std::cerr, 8 );
 					std::cerr << std::endl << " to ";
-					(*formal)->get_type()->print( std::cerr, 8 );
+					(*formalType)->print( std::cerr, 8 );
 				)
 				Cost newCost = conversionCost( *actualType, *formalType, indexer, alt.env );
@@ -511,6 +511,8 @@
 		if ( ! cur->second ) {
 			inferRecursive( begin, end, newAlt, openVars, decls, newNeed, /*needParents,*/ level, indexer, out );
+			return; // xxx - should this continue? previously this wasn't here, and it looks like it should be
 		}
 		DeclarationWithType *curDecl = cur->first;
+
 		PRINT(
 			std::cerr << "inferRecursive: assertion is ";
@@ -649,5 +651,4 @@
 		AltList candidates;
 		SemanticError errors;
-
 		for ( AltList::const_iterator func = funcFinder.alternatives.begin(); func != funcFinder.alternatives.end(); ++func ) {
 			try {
@@ -758,4 +759,5 @@
 	void AlternativeFinder::visit( CastExpr *castExpr ) {
 		Type *& toType = castExpr->get_result();
+		assert( toType );
 		toType = resolveTypeof( toType, indexer );
 		SymTab::validateType( toType, &indexer );
@@ -763,4 +765,5 @@
 
 		AlternativeFinder finder( indexer, env );
+		finder.targetType = toType;
 		finder.findWithAdjustment( castExpr->get_arg() );
 
@@ -776,5 +779,6 @@
 			int discardedValues = (*i).expr->get_result()->size() - castExpr->get_result()->size();
 			if ( discardedValues < 0 ) continue;
-			// xxx - may need to go into tuple types and extract relavent types and use unifyList
+			// xxx - may need to go into tuple types and extract relevant types and use unifyList. Note that currently, this does not
+			// allow casting a tuple to an atomic type (e.g. (int)([1, 2, 3]))
 			// unification run for side-effects
 			unify( castExpr->get_result(), (*i).expr->get_result(), i->env, needAssertions, haveAssertions, openVars, indexer );
@@ -783,7 +787,29 @@
 				// count one safe conversion for each value that is thrown away
 				thisCost += Cost( 0, 0, discardedValues );
-				CastExpr *newExpr = castExpr->clone();
-				newExpr->set_arg( i->expr->clone() );
-				candidates.push_back( Alternative( newExpr, i->env, i->cost, thisCost ) );
+
+				Expression * argExpr = i->expr->clone();
+				if ( argExpr->get_result()->size() > 1 && ! castExpr->get_result()->isVoid() ) {
+					// Argument expression is a tuple and the target type is not void. Cast each member of the tuple
+					// to its corresponding target type, producing the tuple of those cast expressions. If there are
+					// more components of the tuple than components in the target type, then excess components do not
+					// come out in the result expression (but UniqueExprs ensure that side effects will still be done).
+					if ( Tuples::maybeImpure( argExpr ) && ! dynamic_cast< UniqueExpr * >( argExpr ) ) {
+						// expressions which may contain side effects require a single unique instance of the expression.
+						argExpr = new UniqueExpr( argExpr );
+					}
+					std::list< Expression * > componentExprs;
+					for ( unsigned int i = 0; i < castExpr->get_result()->size(); i++ ) {
+						// cast each component
+						TupleIndexExpr * idx = new TupleIndexExpr( argExpr->clone(), i );
+						componentExprs.push_back( new CastExpr( idx, castExpr->get_result()->getComponent( i )->clone() ) );
+					}
+					delete argExpr;
+					assert( componentExprs.size() > 0 );
+					// produce the tuple of casts
+					candidates.push_back( Alternative( new TupleExpr( componentExprs ), i->env, i->cost, thisCost ) );
+				} else {
+					// handle normally
+					candidates.push_back( Alternative( new CastExpr( argExpr->clone(), toType->clone() ), i->env, i->cost, thisCost ) );
+				}
 			} // if
 		} // for
Index: src/ResolvExpr/AlternativeFinder.h
===================================================================
--- src/ResolvExpr/AlternativeFinder.h	(revision fc638d2176b72a88b406e73af7f7f9e548ae05f7)
+++ src/ResolvExpr/AlternativeFinder.h	(revision 793335167c5347f27e76d8ab9f3434b795a6602d)
@@ -91,4 +91,5 @@
 		AltList alternatives;
 		const TypeEnvironment &env;
+		Type * targetType = nullptr;
 	}; // AlternativeFinder
 
Index: src/SynTree/Type.h
===================================================================
--- src/SynTree/Type.h	(revision fc638d2176b72a88b406e73af7f7f9e548ae05f7)
+++ src/SynTree/Type.h	(revision 793335167c5347f27e76d8ab9f3434b795a6602d)
@@ -72,4 +72,5 @@
 	virtual unsigned size() const { return 1; };
 	virtual bool isVoid() const { return size() == 0; }
+	virtual Type * getComponent( unsigned i ) { assertf( size() == 1 && i == 0, "Type::getComponent was called with size %d and index %d\n", size(), i ); return this; }
 
 	virtual Type *clone() const = 0;
@@ -372,4 +373,9 @@
 	iterator end() { return types.end(); }
 
+	virtual Type * getComponent( unsigned i ) {
+		assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d", i, size() );
+		return *(begin()+i);
+	}
+
 	virtual TupleType *clone() const { return new TupleType( *this ); }
 	virtual void accept( Visitor &v ) { v.visit( this ); }
Index: src/tests/.expect/castError.txt
===================================================================
--- src/tests/.expect/castError.txt	(revision fc638d2176b72a88b406e73af7f7f9e548ae05f7)
+++ src/tests/.expect/castError.txt	(revision 793335167c5347f27e76d8ab9f3434b795a6602d)
@@ -1,4 +1,4 @@
 CFA Version 1.0.0 (debug)
-Error: Can't choose between alternatives for expression Cast of:
+Error: Can't choose between 3 alternatives for expression Cast of:
   Name: f
 
Index: src/tests/.expect/tupleCast.txt
===================================================================
--- src/tests/.expect/tupleCast.txt	(revision fc638d2176b72a88b406e73af7f7f9e548ae05f7)
+++ src/tests/.expect/tupleCast.txt	(revision 793335167c5347f27e76d8ab9f3434b795a6602d)
@@ -1,4 +1,5 @@
 10 A 3.14
 10 A
+10
 10 65
 ran f
Index: src/tests/tupleCast.c
===================================================================
--- src/tests/tupleCast.c	(revision fc638d2176b72a88b406e73af7f7f9e548ae05f7)
+++ src/tests/tupleCast.c	(revision 793335167c5347f27e76d8ab9f3434b795a6602d)
@@ -20,4 +20,6 @@
   printf("%d %c %g\n", ([int, char, float])x);
   printf("%d %c\n", ([int, char])x);
+  printf("%d\n", ([int])x);
+  // printf("%d\n", (int)x);
   printf("%g %g\n", ([double, float])x);
   printf("%d %c\n", ([int, char])f());
