Index: src/ResolvExpr/Alternative.h
===================================================================
--- src/ResolvExpr/Alternative.h	(revision a8b27c63155718a34534b0647bd76f979bc66cdf)
+++ src/ResolvExpr/Alternative.h	(revision 62194cbf579b5084c2ebfafd9003eb7b9cb0fa7b)
@@ -37,4 +37,11 @@
 		void print( std::ostream &os, Indenter indent = {} ) const;
 
+		/// Returns the stored expression, but released from management of this Alternative
+		Expression* release_expr() {
+			Expression* tmp = expr;
+			expr = nullptr;
+			return tmp;
+		}
+
 		Cost cost;
 		Cost cvtCost;
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision a8b27c63155718a34534b0647bd76f979bc66cdf)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 62194cbf579b5084c2ebfafd9003eb7b9cb0fa7b)
@@ -676,23 +676,18 @@
 					auto nextArg = results[i].nextArg;
 
-					// use remainder of exploded tuple if present
+					// use next element of exploded tuple if present
 					if ( results[i].hasExpl() ) {
 						const ExplodedActual& expl = results[i].getExpl( args );
-						const Alternative& actual = expl.alts[results[i].nextExpl];
 						
-						TypeEnvironment env = results[i].env;
-						OpenVarSet openVars = results[i].openVars;
-
-						env.addActual( actual.env, openVars );
-
 						unsigned nextExpl = results[i].nextExpl + 1;
-						if ( nextExpl == expl.alts.size() ) {
+						if ( nextExpl == expl.exprs.size() ) {
 							nextExpl = 0;
 						}
 
 						results.emplace_back(
-							i, actual.expr, move(env), copy(results[i].need), 
-							copy(results[i].have), move(openVars), nextArg, nTuples, 
-							Cost::zero, nextExpl, results[i].explAlt );
+							i, expl.exprs[results[i].nextExpl].get(), copy(results[i].env), 
+							copy(results[i].need), copy(results[i].have), 
+							copy(results[i].openVars), nextArg, nTuples, Cost::zero, nextExpl, 
+							results[i].explAlt );
 						
 						continue;
@@ -758,5 +753,5 @@
 
 						// skip empty tuple arguments by (near-)cloning parent into next gen
-						if ( expl.alts.empty() ) {
+						if ( expl.exprs.empty() ) {
 							results.emplace_back(
 								results[i], move(env), copy(results[i].need), 
@@ -768,7 +763,7 @@
 						// add new result
 						results.emplace_back(
-							i, expl.alts.front().expr, move(env), copy(results[i].need), 
+							i, expl.exprs.front().get(), move(env), copy(results[i].need), 
 							copy(results[i].have), move(openVars), nextArg + 1, 
-							nTuples, expl.cost, expl.alts.size() == 1 ? 0 : 1, j );
+							nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
 					}
 				}
@@ -794,5 +789,5 @@
 			if ( results[i].hasExpl() ) {
 				const ExplodedActual& expl = results[i].getExpl( args );
-				const Alternative& actual = expl.alts[results[i].nextExpl];
+				Expression* expr = expl.exprs[results[i].nextExpl].get();
 				
 				TypeEnvironment env = results[i].env;
@@ -800,6 +795,5 @@
 				OpenVarSet openVars = results[i].openVars;
 
-				env.addActual( actual.env, openVars );
-				Type* actualType = actual.expr->get_result();
+				Type* actualType = expr->get_result();
 
 				PRINT(
@@ -813,11 +807,11 @@
 				if ( unify( formalType, actualType, env, need, have, openVars, indexer ) ) {
 					unsigned nextExpl = results[i].nextExpl + 1;
-					if ( nextExpl == expl.alts.size() ) {
+					if ( nextExpl == expl.exprs.size() ) {
 						nextExpl = 0;
 					}
 					
 					results.emplace_back( 
-						i, actual.expr, move(env), move(need), move(have), move(openVars), 
-						nextArg, nTuples, Cost::zero, nextExpl, results[i].explAlt );
+						i, expr, move(env), move(need), move(have), move(openVars), nextArg, 
+						nTuples, Cost::zero, nextExpl, results[i].explAlt );
 				}
 
@@ -857,5 +851,5 @@
 				
 				// skip empty tuple arguments by (near-)cloning parent into next gen
-				if ( expl.alts.empty() ) {
+				if ( expl.exprs.empty() ) {
 					results.emplace_back(
 						results[i], move(env), move(need), move(have), move(openVars), 
@@ -866,6 +860,6 @@
 
 				// consider only first exploded actual
-				const Alternative& actual = expl.alts.front();
-				Type* actualType = actual.expr->get_result()->clone();
+				Expression* expr = expl.exprs.front().get();
+				Type* actualType = expr->get_result()->clone();
 
 				PRINT(
@@ -881,6 +875,6 @@
 					// add new result
 					results.emplace_back(
-						i, actual.expr, move(env), move(need), move(have), move(openVars),
-						nextArg + 1, nTuples, expl.cost, expl.alts.size() == 1 ? 0 : 1, j );
+						i, expr, move(env), move(need), move(have), move(openVars), nextArg + 1, 
+						nTuples, expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
 				}
 			}
@@ -962,20 +956,15 @@
 					if ( results[i].hasExpl() ) {
 						const ExplodedActual& expl = results[i].getExpl( args );
-						const Alternative& actual = expl.alts[results[i].nextExpl];
 						
-						TypeEnvironment env = results[i].env;
-						OpenVarSet openVars = results[i].openVars;
-
-						env.addActual( actual.env, openVars );
-
 						unsigned nextExpl = results[i].nextExpl + 1;
-						if ( nextExpl == expl.alts.size() ) {
+						if ( nextExpl == expl.exprs.size() ) {
 							nextExpl = 0;
 						}
 
 						results.emplace_back(
-							i, actual.expr, move(env), copy(results[i].need), 
-							copy(results[i].have), move(openVars), nextArg, 0, 
-							Cost::zero, nextExpl, results[i].explAlt );
+							i, expl.exprs[results[i].nextExpl].get(), copy(results[i].env), 
+							copy(results[i].need), copy(results[i].have), 
+							copy(results[i].openVars), nextArg, 0, Cost::zero, nextExpl, 
+							results[i].explAlt );
 						
 						continue;
@@ -1000,5 +989,5 @@
 
 						// skip empty tuple arguments by (near-)cloning parent into next gen
-						if ( expl.alts.empty() ) {
+						if ( expl.exprs.empty() ) {
 							results.emplace_back( 
 								results[i], move(env), copy(results[i].need), 
@@ -1010,7 +999,7 @@
 						// add new result
 						results.emplace_back(
-							i, expl.alts.front().expr, move(env), copy(results[i].need), 
+							i, expl.exprs.front().get(), move(env), copy(results[i].need), 
 							copy(results[i].have), move(openVars), nextArg + 1, 0, 
-							expl.cost, expl.alts.size() == 1 ? 0 : 1, j );
+							expl.cost, expl.exprs.size() == 1 ? 0 : 1, j );
 					}
 				}
Index: src/ResolvExpr/ExplodedActual.cc
===================================================================
--- src/ResolvExpr/ExplodedActual.cc	(revision a8b27c63155718a34534b0647bd76f979bc66cdf)
+++ src/ResolvExpr/ExplodedActual.cc	(revision 62194cbf579b5084c2ebfafd9003eb7b9cb0fa7b)
@@ -20,6 +20,6 @@
 namespace ResolvExpr {
 	ExplodedActual::ExplodedActual( const Alternative& actual, const SymTab::Indexer& indexer ) 
-			: env(actual.env), cost(actual.cost), alts() {
-		Tuples::explode( actual, indexer, back_inserter( alts ) );
+			: env(actual.env), cost(actual.cost), exprs() {
+		Tuples::explode( actual, indexer, *this );
 	}
 }
Index: src/ResolvExpr/ExplodedActual.h
===================================================================
--- src/ResolvExpr/ExplodedActual.h	(revision a8b27c63155718a34534b0647bd76f979bc66cdf)
+++ src/ResolvExpr/ExplodedActual.h	(revision 62194cbf579b5084c2ebfafd9003eb7b9cb0fa7b)
@@ -16,4 +16,7 @@
 #pragma once
 
+#include <memory>
+#include <vector>
+
 #include "Alternative.h"      // for Alternative, AltList
 #include "Cost.h"             // for Cost
@@ -26,9 +29,9 @@
 		TypeEnvironment env;
 		Cost cost;
-		AltList alts;  // TODO flatten this down to vector<unique_ptr<Expression>>
+		std::vector< std::unique_ptr<Expression> > exprs;
 
-		ExplodedActual() : env(), cost(Cost::zero), alts() {}
+		ExplodedActual() : env(), cost(Cost::zero), exprs() {}
 
-		ExplodedActual( const Alternative& actual, const SymTab::Indexer& indexer );	
+		ExplodedActual( const Alternative& actual, const SymTab::Indexer& indexer );
 	};
 }
Index: src/Tuples/Explode.h
===================================================================
--- src/Tuples/Explode.h	(revision a8b27c63155718a34534b0647bd76f979bc66cdf)
+++ src/Tuples/Explode.h	(revision 62194cbf579b5084c2ebfafd9003eb7b9cb0fa7b)
@@ -16,10 +16,12 @@
 #pragma once
 
-#include <iterator>                  // for back_inserter, back_insert_iterator
+#include <iterator>                     // for back_inserter, back_insert_iterator
+#include <utility>                      // for forward
 
-#include "ResolvExpr/Alternative.h"  // for Alternative, AltList
-#include "SynTree/Expression.h"      // for Expression, UniqueExpr, AddressExpr
-#include "SynTree/Type.h"            // for TupleType, Type
-#include "Tuples.h"                  // for maybeImpure
+#include "ResolvExpr/Alternative.h"     // for Alternative, AltList
+#include "ResolvExpr/ExplodedActual.h"  // for ExplodedActual
+#include "SynTree/Expression.h"         // for Expression, UniqueExpr, AddressExpr
+#include "SynTree/Type.h"               // for TupleType, Type
+#include "Tuples.h"                     // for maybeImpure
 
 namespace SymTab {
@@ -39,16 +41,32 @@
 	}
 
+	/// Append alternative to an OutputIterator of Alternatives
+	template<typename OutputIterator>
+	void append( OutputIterator out, Expression* expr, const ResolvExpr::TypeEnvironment& env, 
+			const ResolvExpr::Cost& cost, const ResolvExpr::Cost& cvtCost ) {
+		*out++ = ResolvExpr::Alternative{ expr, env, cost, cvtCost };
+	}
+
+	/// Append alternative to an ExplodedActual
+	static inline void append( ResolvExpr::ExplodedActual& ea, Expression* expr, 
+			const ResolvExpr::TypeEnvironment&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
+		ea.exprs.emplace_back( expr );
+		/// xxx -- merge environment, cost?
+	}
+
 	/// helper function used by explode
-	template< typename OutputIterator >
-	void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt, const SymTab::Indexer & indexer, OutputIterator out, bool isTupleAssign ) {
+	template< typename Output >
+	void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt, 
+			const SymTab::Indexer & indexer, Output&& out, bool isTupleAssign ) {
 		if ( isTupleAssign ) {
 			// tuple assignment needs CastExprs to be recursively exploded to easily get at all of the components
 			if ( CastExpr * castExpr = isReferenceCast( expr ) ) {
 				ResolvExpr::AltList alts;
-				explodeUnique( castExpr->get_arg(), alt, indexer, back_inserter( alts ), isTupleAssign );
+				explodeUnique( 
+					castExpr->get_arg(), alt, indexer, back_inserter( alts ), isTupleAssign );
 				for ( ResolvExpr::Alternative & alt : alts ) {
 					// distribute reference cast over all components
-					alt.expr = distributeReference( alt.expr );
-					*out++ = alt;
+					append( std::forward<Output>(out), distributeReference( alt.release_expr() ), 
+						alt.env, alt.cost, alt.cvtCost );
 				}
 				// in tuple assignment, still need to handle the other cases, but only if not already handled here (don't want to output too many alternatives)
@@ -61,5 +79,5 @@
 				// can open tuple expr and dump its exploded components
 				for ( Expression * expr : tupleExpr->get_exprs() ) {
-					explodeUnique( expr, alt, indexer, out, isTupleAssign );
+					explodeUnique( expr, alt, indexer, std::forward<Output>(out), isTupleAssign );
 				}
 			} else {
@@ -77,5 +95,5 @@
 				for ( unsigned int i = 0; i < tupleType->size(); i++ ) {
 					TupleIndexExpr * idx = new TupleIndexExpr( arg->clone(), i );
-					explodeUnique( idx, alt, indexer, out, isTupleAssign );
+					explodeUnique( idx, alt, indexer, std::forward<Output>(out), isTupleAssign );
 					delete idx;
 				}
@@ -84,25 +102,28 @@
 		} else {
 			// atomic (non-tuple) type - output a clone of the expression in a new alternative
-			*out++ = ResolvExpr::Alternative( expr->clone(), alt.env, alt.cost, alt.cvtCost );
+			append( std::forward<Output>(out), expr->clone(), alt.env, alt.cost, alt.cvtCost );
 		}
 	}
 
 	/// expands a tuple-valued alternative into multiple alternatives, each with a non-tuple-type
-	template< typename OutputIterator >
-	void explode( const ResolvExpr::Alternative &alt, const SymTab::Indexer & indexer, OutputIterator out, bool isTupleAssign = false ) {
-		explodeUnique( alt.expr, alt, indexer, out, isTupleAssign );
+	template< typename Output >
+	void explode( const ResolvExpr::Alternative &alt, const SymTab::Indexer & indexer, 
+			Output&& out, bool isTupleAssign = false ) {
+		explodeUnique( alt.expr, alt, indexer, std::forward<Output>(out), isTupleAssign );
 	}
 
 	// explode list of alternatives
-	template< typename AltIterator, typename OutputIterator >
-	void explode( AltIterator altBegin, AltIterator altEnd, const SymTab::Indexer & indexer, OutputIterator out, bool isTupleAssign = false ) {
+	template< typename AltIterator, typename Output >
+	void explode( AltIterator altBegin, AltIterator altEnd, const SymTab::Indexer & indexer, 
+			Output&& out, bool isTupleAssign = false ) {
 		for ( ; altBegin != altEnd; ++altBegin ) {
-			explode( *altBegin, indexer, out, isTupleAssign );
+			explode( *altBegin, indexer, std::forward<Output>(out), isTupleAssign );
 		}
 	}
 
-	template< typename OutputIterator >
-	void explode( const ResolvExpr::AltList & alts, const SymTab::Indexer & indexer, OutputIterator out, bool isTupleAssign = false ) {
-		explode( alts.begin(), alts.end(), indexer, out, isTupleAssign );
+	template< typename Output >
+	void explode( const ResolvExpr::AltList & alts, const SymTab::Indexer & indexer, Output&& out, 
+			bool isTupleAssign = false ) {
+		explode( alts.begin(), alts.end(), indexer, std::forward<Output>(out), isTupleAssign );
 	}
 } // namespace Tuples
