Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision a1e67ddc023331e04cc5481931be1d0923efc441)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision 77971f6131006ff573ba5422c4d83b41b7c5e612)
@@ -41,4 +41,5 @@
 #include "Common/utility.h"
 #include "InitTweak/InitTweak.h"
+#include "InitTweak/GenInit.h"
 #include "ResolveTypeof.h"
 
@@ -207,7 +208,8 @@
 	}
 
+	// std::unordered_map< Expression *, UniqueExpr * > ;
+
 	template< typename StructOrUnionType >
 	void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
-
 		// by this point, member must be a name expr
 		NameExpr * nameExpr = safe_dynamic_cast< NameExpr * >( member );
@@ -434,5 +436,5 @@
 		// flatten actuals so that each actual has an atomic (non-tuple) type
 		AltList exploded;
-		Tuples::explode( actuals, back_inserter( exploded ) );
+		Tuples::explode( actuals, indexer, back_inserter( exploded ) );
 
 		AltList::iterator actualExpr = exploded.begin();
@@ -1055,16 +1057,21 @@
 
 	void AlternativeFinder::visit( UniqueExpr *unqExpr ) {
+		// this won't work because the unqExprs wont share an expression anymore...
 		AlternativeFinder finder( indexer, env );
 		finder.findWithAdjustment( unqExpr->get_expr() );
 		for ( Alternative & alt : finder.alternatives ) {
-			// xxx - it's possible that this won't always do the right thing, i.e. two UniqueExprs
-			// with the same ID may resolve to different expressions. If this ever happens, it might be necessary
-			// to try to select an alternative here (i.e. error is there is not a unique min-cost expression).
-			// One other thought is to to resolve each ID once and map the IDs to resolved expressions,
-			// but this isn't as simple as it sounds since the alternative is not selected here, meaning it might
-			// require complicated tracking throughout the system.
-
-			// brand the new UniqueExprs with the same id so that they are recognized as the same expression by the expansion pass
-			alternatives.push_back( Alternative( new UniqueExpr( alt.expr->clone(), unqExpr->get_id() ), env, Cost::zero ) );
+			// xxx - attach a resolved ConstructorInit node?
+			// xxx - is it possible to make the objDecl's type const?
+			static UniqueName tempNamer( "_unq_expr_" );
+			ObjectDecl * objDecl = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, alt.expr->get_result()->clone(), nullptr );
+			// must be done on two lines because genCtorInit accesses objDecl's fields
+			objDecl->set_init( InitTweak::genCtorInit( objDecl ) );
+
+			UniqueExpr * newUnqExpr = new UniqueExpr( alt.expr->clone(), unqExpr->get_id() );
+			newUnqExpr->set_object( objDecl );
+
+			resolveObject( indexer, objDecl );
+
+			alternatives.push_back( Alternative( newUnqExpr, env, Cost::zero ) );
 		}
 	}
Index: src/ResolvExpr/AlternativeFinder.h
===================================================================
--- src/ResolvExpr/AlternativeFinder.h	(revision a1e67ddc023331e04cc5481931be1d0923efc441)
+++ src/ResolvExpr/AlternativeFinder.h	(revision 77971f6131006ff573ba5422c4d83b41b7c5e612)
@@ -95,4 +95,6 @@
 	Expression *resolveInVoidContext( Expression *expr, const SymTab::Indexer &indexer, TypeEnvironment &env );
 
+	void resolveObject( const SymTab::Indexer & indexer, ObjectDecl * objectDecl );
+
 	template< typename InputIterator, typename OutputIterator >
 	void findMinCost( InputIterator begin, InputIterator end, OutputIterator out ) {
Index: src/ResolvExpr/Resolver.cc
===================================================================
--- src/ResolvExpr/Resolver.cc	(revision a1e67ddc023331e04cc5481931be1d0923efc441)
+++ src/ResolvExpr/Resolver.cc	(revision 77971f6131006ff573ba5422c4d83b41b7c5e612)
@@ -35,5 +35,6 @@
 	class Resolver : public SymTab::Indexer {
 	  public:
-		Resolver() : SymTab::Indexer( false ), switchType( 0 ) {}
+		Resolver() : SymTab::Indexer( false ) {}
+		Resolver( const SymTab::Indexer & indexer ) : SymTab::Indexer( indexer ) {}
 
 		virtual void visit( FunctionDecl *functionDecl );
@@ -68,7 +69,7 @@
 	  void resolveSingleAggrInit( Declaration *, InitIterator &, InitIterator & );
 	  void fallbackInit( ConstructorInit * ctorInit );
-		Type * functionReturn;
-		Type *initContext;
-		Type *switchType;
+		Type * functionReturn = nullptr;
+		Type *initContext = nullptr;
+		Type *switchType = nullptr;
 		bool inEnumDecl = false;
 	};
@@ -532,4 +533,9 @@
 	}
 
+	void resolveObject( const SymTab::Indexer & indexer, ObjectDecl * objectDecl ) {
+		Resolver resolver( indexer );
+		objectDecl->accept( resolver );
+	}
+
 	void Resolver::visit( ConstructorInit *ctorInit ) {
 		// xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit
Index: src/SynTree/Expression.cc
===================================================================
--- src/SynTree/Expression.cc	(revision a1e67ddc023331e04cc5481931be1d0923efc441)
+++ src/SynTree/Expression.cc	(revision 77971f6131006ff573ba5422c4d83b41b7c5e612)
@@ -581,5 +581,5 @@
 
 long long UniqueExpr::count = 0;
-UniqueExpr::UniqueExpr( Expression *expr, long long idVal ) : expr( new Expression* ), id( idVal ) {
+UniqueExpr::UniqueExpr( Expression *expr, long long idVal ) : expr( new Expression* ), object( new ObjectDecl* ), id( idVal ) {
 	assert( count != -1 );
 	if ( id == -1 ) id = count++;
@@ -589,6 +589,7 @@
 		set_result( expr->get_result()->clone() );
 	}
-}
-UniqueExpr::UniqueExpr( const UniqueExpr &other ) : Expression( other ), expr( other.expr ), id( other.id ) {
+	set_object( nullptr );
+}
+UniqueExpr::UniqueExpr( const UniqueExpr &other ) : Expression( other ), expr( other.expr ), object( other.object ), id( other.id ) {
 }
 UniqueExpr::~UniqueExpr() {
@@ -596,8 +597,15 @@
 		delete *expr;
 	}
+	if ( object.unique() ) {
+		delete *object;
+	}
 }
 void UniqueExpr::print( std::ostream &os, int indent ) const {
 	os << "Unique Expression with id:" << id << std::endl << std::string( indent+2, ' ' );
 	get_expr()->print( os, indent+2 );
+	if ( get_object() ) {
+		os << " with decl: ";
+		get_object()->printShort( os, indent+2 );
+	}
 }
 
Index: src/SynTree/Expression.h
===================================================================
--- src/SynTree/Expression.h	(revision a1e67ddc023331e04cc5481931be1d0923efc441)
+++ src/SynTree/Expression.h	(revision 77971f6131006ff573ba5422c4d83b41b7c5e612)
@@ -742,4 +742,7 @@
 	UniqueExpr * set_expr( Expression * newValue ) { *expr = newValue; return this; }
 
+	ObjectDecl * get_object() const { return *object; }
+	UniqueExpr * set_object( ObjectDecl * newValue ) { *object = newValue; return this; }
+
 	int get_id() const { return id; }
 
@@ -750,4 +753,5 @@
 private:
 	std::shared_ptr< Expression * > expr;
+	std::shared_ptr< ObjectDecl * > object;
 	int id;
 	static long long count;
Index: src/Tuples/TupleAssignment.cc
===================================================================
--- src/Tuples/TupleAssignment.cc	(revision a1e67ddc023331e04cc5481931be1d0923efc441)
+++ src/Tuples/TupleAssignment.cc	(revision 77971f6131006ff573ba5422c4d83b41b7c5e612)
@@ -179,5 +179,5 @@
 
 		// explode the lhs so that each field of the tuple-valued-expr is assigned.
-		explode( lhsAlt, back_inserter(lhs) );
+		explode( lhsAlt, spotter.currentFinder.get_indexer(), back_inserter(lhs) );
 		// and finally, re-add the cast to each lhs expr, so that qualified tuple fields can be constructed
 		if ( isCast ) {
@@ -204,5 +204,5 @@
 	TupleAssignSpotter::MultipleAssignMatcher::MultipleAssignMatcher( TupleAssignSpotter &spotter, const ResolvExpr::AltList & alts ) : Matcher( spotter, alts ) {
 		// explode the rhs so that each field of the tuple-valued-expr is assigned.
-		explode( std::next(alts.begin(), 1), alts.end(), back_inserter(rhs) );
+		explode( std::next(alts.begin(), 1), alts.end(), spotter.currentFinder.get_indexer(), back_inserter(rhs) );
 	}
 
Index: src/Tuples/TupleExpansion.cc
===================================================================
--- src/Tuples/TupleExpansion.cc	(revision a1e67ddc023331e04cc5481931be1d0923efc441)
+++ src/Tuples/TupleExpansion.cc	(revision 77971f6131006ff573ba5422c4d83b41b7c5e612)
@@ -141,5 +141,4 @@
 
 	Expression * UniqueExprExpander::mutate( UniqueExpr * unqExpr ) {
-		static UniqueName tempNamer( "_unq_expr_" );
 		unqExpr = safe_dynamic_cast< UniqueExpr * > ( Parent::mutate( unqExpr ) );
 		if ( ! decls.count( unqExpr->get_id() ) ) {
@@ -160,10 +159,6 @@
 			// }
 
-			// xxx - attach a resolved ConstructorInit node?
-			// xxx - is it possible to make the objDecl's type const?
-			ObjectDecl * objDecl = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, nullptr, unqExpr->get_result()->clone(), nullptr );
-			// must be done on two lines because genCtorInit accesses objDecl's fields
-			objDecl->set_init( InitTweak::genCtorInit( objDecl ) );
-
+			ObjectDecl * objDecl = unqExpr->get_object();
+			unqExpr->set_object( nullptr );
 			decls[unqExpr->get_id()] = objDecl;
 			addDeclaration( objDecl );
Index: src/Tuples/Tuples.h
===================================================================
--- src/Tuples/Tuples.h	(revision a1e67ddc023331e04cc5481931be1d0923efc441)
+++ src/Tuples/Tuples.h	(revision 77971f6131006ff573ba5422c4d83b41b7c5e612)
@@ -20,4 +20,5 @@
 #include <vector>
 #include "ResolvExpr/AlternativeFinder.h"
+#include "ResolvExpr/Resolver.h"
 
 #include "SynTree/Expression.h"
@@ -48,9 +49,9 @@
 	/// helper function used by explode
 	template< typename OutputIterator >
-	void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt, OutputIterator out ) {
+	void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt, const SymTab::Indexer & indexer, OutputIterator out ) {
 		Type * res = expr->get_result();
 		if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( expr ) ) {
 			ResolvExpr::AltList alts;
-			explodeUnique( addrExpr->get_arg(), alt, back_inserter( alts ) );
+			explodeUnique( addrExpr->get_arg(), alt, indexer, back_inserter( alts ) );
 			for ( ResolvExpr::Alternative & alt : alts ) {
 				// distribute '&' over all components
@@ -62,5 +63,5 @@
 				// can open tuple expr and dump its exploded components
 				for ( Expression * expr : tupleExpr->get_exprs() ) {
-					explodeUnique( expr, alt, out );
+					explodeUnique( expr, alt, indexer, out );
 				}
 			} else {
@@ -68,10 +69,13 @@
 				Expression * arg = expr->clone();
 				if ( Tuples::maybeImpure( arg ) ) {
-					// expressions which may contain side effects require a single unique instance of the expression
+					// expressions which may contain side effects require a single unique instance of the expression.
+					// resolve the UniqueExpr (which should be relatively cheap, since the argument is already resolved)
+					// so that its accompanying object is properly constructed and destructed.
 					arg = new UniqueExpr( arg );
+					arg = ResolvExpr::resolveInVoidContext( arg, indexer );
 				}
 				for ( unsigned int i = 0; i < tupleType->size(); i++ ) {
 					TupleIndexExpr * idx = new TupleIndexExpr( arg->clone(), i );
-					explodeUnique( idx, alt, out );
+					explodeUnique( idx, alt, indexer, out );
 					delete idx;
 				}
@@ -86,19 +90,19 @@
 	/// expands a tuple-valued alternative into multiple alternatives, each with a non-tuple-type
 	template< typename OutputIterator >
-	void explode( const ResolvExpr::Alternative &alt, OutputIterator out ) {
-		explodeUnique( alt.expr, alt, out );
+	void explode( const ResolvExpr::Alternative &alt, const SymTab::Indexer & indexer, OutputIterator out ) {
+		explodeUnique( alt.expr, alt, indexer, out );
 	}
 
 	// explode list of alternatives
 	template< typename AltIterator, typename OutputIterator >
-	void explode( AltIterator altBegin, AltIterator altEnd, OutputIterator out ) {
+	void explode( AltIterator altBegin, AltIterator altEnd, const SymTab::Indexer & indexer, OutputIterator out ) {
 		for ( ; altBegin != altEnd; ++altBegin ) {
-			explode( *altBegin, out );
+			explode( *altBegin, indexer, out );
 		}
 	}
 
 	template< typename OutputIterator >
-	void explode( const ResolvExpr::AltList & alts, OutputIterator out ) {
-		explode( alts.begin(), alts.end(), out );
+	void explode( const ResolvExpr::AltList & alts, const SymTab::Indexer & indexer, OutputIterator out ) {
+		explode( alts.begin(), alts.end(), indexer, out );
 	}
 } // namespace Tuples
