Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision e472d54add7ff0b5a6cccd337055f238354337a6)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision a5853962bf23b5d7a28c561f2c6749df02ac9144)
@@ -579,14 +579,18 @@
 			  tupleEls() {}
 		
-		ArgPack(const ArgPack& old, Expression* actual, const Cost& cost = Cost::zero)
-			: actuals(old.actuals), env(old.env), need(old.need), have(old.have), 
-			  openVars(old.openVars), nextArg(old.nextArg + 1), tupleEls(old.tupleEls) {
+		ArgPack(const ArgPack& old, Expression* actual, TypeEnvironment&& env, 
+				OpenVarSet&& openVars, const Cost& cost = Cost::zero)
+			: actuals(old.actuals), env(std::move(env)), need(old.need), have(old.have), 
+			  openVars(std::move(openVars)), nextArg(old.nextArg + 1), tupleEls(old.tupleEls) {
+			// add new actual
 			actuals.emplace_back( actual, this->env, cost );
+			// count tuple elements, if applicable
+			if ( ! tupleEls.empty() ) ++tupleEls.back();
 		}
 		
 		ArgPack(const ArgPack& old, Expression* actual, TypeEnvironment&& env, AssertionSet&& need, 
-				AssertionSet&& have, const Cost& cost = Cost::zero)
+				AssertionSet&& have, OpenVarSet&& openVars, const Cost& cost = Cost::zero)
 			: actuals(old.actuals), env(std::move(env)), need(std::move(need)), 
-			  have(std::move(have)), openVars(old.openVars), nextArg(old.nextArg + 1), 
+			  have(std::move(have)), openVars(std::move(openVars)), nextArg(old.nextArg + 1), 
 			  tupleEls(old.tupleEls) {
 			// add new actual
@@ -713,7 +717,11 @@
 					for ( const Alternative& actual : args[result.nextArg] ) {
 						addExplodedActual( result, actual.expr, actual.cost, nextResults, 
-							[]( ArgPack& result, Expression* expr, Cost cost, 
+							[&actual]( ArgPack& result, Expression* expr, Cost cost, 
 									std::vector<ArgPack>& nextResults ) {
-								nextResults.emplace_back( result, expr, cost );
+								TypeEnvironment env{ result.env };
+								OpenVarSet openVars{ result.openVars };
+								env.addActual( actual.env, openVars );
+								nextResults.emplace_back( result, expr, std::move(env), 
+									std::move(openVars), cost );
 							} );
 					}
@@ -741,5 +749,5 @@
 							nextResults.emplace_back( result, cnstExpr->clone(), 
 								std::move(resultEnv), std::move(resultNeed), 
-								std::move(resultHave) );
+								std::move(resultHave), OpenVarSet{ result.openVars } );
 						}
 					}
@@ -751,10 +759,13 @@
 			for ( const Alternative& actual : args[result.nextArg] ) {
 				addExplodedActual( result, actual.expr, actual.cost, nextResults, 
-					[formalType,&indexer]( ArgPack& result, Expression* expr, Cost cost, 
+					[formalType,&indexer,&actual]( ArgPack& result, Expression* expr, Cost cost, 
 							std::vector<ArgPack>& nextResults ) {
 						// attempt to unify actual with parameter
 						TypeEnvironment resultEnv = result.env;
 						AssertionSet resultNeed = result.need, resultHave = result.have;
+						OpenVarSet resultOpenVars = result.openVars;
+						resultEnv.addActual( actual.env, resultOpenVars );
 						Type* actualType = expr->get_result();
+
 
 						PRINT(
@@ -767,8 +778,8 @@
 
 						if ( unify( formalType, actualType, resultEnv, resultNeed, resultHave, 
-								result.openVars, indexer ) ) {
+								resultOpenVars, indexer ) ) {
 							nextResults.emplace_back( result, expr->clone(), 
 								std::move(resultEnv), std::move(resultNeed), std::move(resultHave),
-								cost );
+								std::move(resultOpenVars), cost );
 						}
 					} );
@@ -829,5 +840,9 @@
 					// add each possible next argument
 					for ( const Alternative& actual : args[result.nextArg] ) {
-						nextResults.emplace_back( result, actual.expr, actual.cost );
+						TypeEnvironment env{ result.env };
+						OpenVarSet openVars{ result.openVars };
+						env.addActual( actual.env, openVars );
+						nextResults.emplace_back( result, actual.expr, std::move(env), 
+							std::move(openVars), actual.cost );
 					}
 				}
@@ -1368,4 +1383,5 @@
 		findSubExprs( tupleExpr->get_exprs().begin(), tupleExpr->get_exprs().end(), back_inserter( subExprAlternatives ) );
 		std::list< AltList > possibilities;
+		// TODO re-write to use iterative method
 		combos( subExprAlternatives.begin(), subExprAlternatives.end(), back_inserter( possibilities ) );
 		for ( std::list< AltList >::const_iterator i = possibilities.begin(); i != possibilities.end(); ++i ) {
Index: src/ResolvExpr/TypeEnvironment.cc
===================================================================
--- src/ResolvExpr/TypeEnvironment.cc	(revision e472d54add7ff0b5a6cccd337055f238354337a6)
+++ src/ResolvExpr/TypeEnvironment.cc	(revision a5853962bf23b5d7a28c561f2c6749df02ac9144)
@@ -201,4 +201,15 @@
 	}
 
+	void TypeEnvironment::addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars ) {
+		for ( const EqvClass& c : actualEnv ) {
+			EqvClass c2 = c;
+			c2.allowWidening = false;
+			for ( const std::string& var : c2.vars ) {
+				openVars[ var ] = c2.data;
+			}
+			env.push_back( std::move(c2) );
+		}
+	}
+
 } // namespace ResolvExpr
 
Index: src/ResolvExpr/TypeEnvironment.h
===================================================================
--- src/ResolvExpr/TypeEnvironment.h	(revision e472d54add7ff0b5a6cccd337055f238354337a6)
+++ src/ResolvExpr/TypeEnvironment.h	(revision a5853962bf23b5d7a28c561f2c6749df02ac9144)
@@ -86,4 +86,8 @@
 		TypeEnvironment *clone() const { return new TypeEnvironment( *this ); }
 
+		/// Iteratively adds the environment of a new actual (with allowWidening = false), 
+		/// and extracts open variables.
+		void addActual( const TypeEnvironment& actualEnv, OpenVarSet& openVars );
+
 		typedef std::list< EqvClass >::iterator iterator;
 		iterator begin() { return env.begin(); }
