Index: src/Tuples/TupleAssignment.cc
===================================================================
--- src/Tuples/TupleAssignment.cc	(revision b8524ca1420ff28d69347f46888a20baa805f797)
+++ src/Tuples/TupleAssignment.cc	(revision 58e280f46565e06007c2e7fc6db8434759dbaef4)
@@ -67,8 +67,8 @@
 		struct Matcher {
 		  public:
-			Matcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs, 
+			Matcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs,
 				const ResolvExpr::AltList& rhs );
 			virtual ~Matcher() {}
-			
+
 			virtual void match( std::list< Expression * > &out ) = 0;
 			ObjectDecl * newObject( UniqueName & namer, Expression * expr );
@@ -83,5 +83,5 @@
 				for ( const ResolvExpr::Alternative& alt : alts ) { combineState( alt ); }
 			}
-			
+
 			ResolvExpr::AltList lhs, rhs;
 			TupleAssignSpotter_old &spotter;
@@ -264,5 +264,5 @@
 		}
 
-		// extract expressions from the assignment alternatives to produce a list of assignments 
+		// extract expressions from the assignment alternatives to produce a list of assignments
 		// that together form a single alternative
 		std::list< Expression *> solved_assigns;
@@ -271,10 +271,10 @@
 			matcher->combineState( alt );
 		}
-		
+
 		// xxx -- was push_front
 		currentFinder.get_alternatives().push_back( ResolvExpr::Alternative{
-			new TupleAssignExpr{ solved_assigns, matcher->tmpDecls }, matcher->compositeEnv, 
-			matcher->openVars, 
-			ResolvExpr::AssertionList( matcher->need.begin(), matcher->need.end() ), 
+			new TupleAssignExpr{ solved_assigns, matcher->tmpDecls }, matcher->compositeEnv,
+			matcher->openVars,
+			ResolvExpr::AssertionList( matcher->need.begin(), matcher->need.end() ),
 			ResolvExpr::sumCost( current ) + matcher->baseCost } );
 	}
@@ -284,5 +284,5 @@
 	: lhs(lhs), rhs(rhs), spotter(spotter),
 	  baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) {
-		combineState( lhs ); 
+		combineState( lhs );
 		combineState( rhs );
 	}
@@ -390,5 +390,5 @@
 		return dynamic_cast< const ast::TupleType * >( expr->result->stripReferences() );
 	}
-	
+
 	/// true if `expr` is of tuple type or a reference to one
 	bool refToTuple( const ast::Expr * expr ) {
@@ -421,18 +421,19 @@
 			}
 
-			Matcher( 
+			Matcher(
 				TupleAssignSpotter_new & s, const CodeLocation & loc,
 				const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r )
-			: lhs( l ), rhs( r ), spotter( s ), location( loc ), 
-			  baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ), tmpDecls(), 
+			: lhs( l ), rhs( r ), spotter( s ), location( loc ),
+			  baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ), tmpDecls(),
 			  env(), open(), need() {
 				for ( auto & cand : lhs ) combineState( *cand );
 				for ( auto & cand : rhs ) combineState( *cand );
 			}
+			virtual ~Matcher() = default;
 
 			virtual std::vector< ast::ptr< ast::Expr > > match() = 0;
 
-			/// removes environments from subexpressions within statement expressions, which could 
-			/// throw off later passes like those in Box which rely on PolyMutator, and adds the 
+			/// removes environments from subexpressions within statement expressions, which could
+			/// throw off later passes like those in Box which rely on PolyMutator, and adds the
 			/// bindings to the env
 			struct EnvRemover {
@@ -455,13 +456,13 @@
 			ast::ObjectDecl * newObject( UniqueName & namer, const ast::Expr * expr ) {
 				assert( expr->result && ! expr->result->isVoid() );
-				
-				ast::ObjectDecl * ret = new ast::ObjectDecl{ 
-					location, namer.newName(), expr->result, new ast::SingleInit{ location, expr }, 
+
+				ast::ObjectDecl * ret = new ast::ObjectDecl{
+					location, namer.newName(), expr->result, new ast::SingleInit{ location, expr },
 					ast::Storage::Classes{}, ast::Linkage::Cforall };
-				
+
 				// if expression type is a reference, just need an initializer, otherwise construct
 				if ( ! expr->result.as< ast::ReferenceType >() ) {
 					// resolve ctor/dtor for the new object
-					ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit( 
+					ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit(
 							InitTweak::genCtorInit( location, ret ), spotter.crntFinder.symtab );
 					// remove environments from subexpressions of stmtExpr
@@ -474,7 +475,7 @@
 			}
 
-			ast::UntypedExpr * createFunc( 
-				const std::string & fname, const ast::ObjectDecl * left, 
-				const ast::ObjectDecl * right 
+			ast::UntypedExpr * createFunc(
+				const std::string & fname, const ast::ObjectDecl * left,
+				const ast::ObjectDecl * right
 			) {
 				assert( left );
@@ -486,8 +487,8 @@
 					args.front() = new ast::AddressExpr{ location, args.front() };
 					if ( right ) { args.back() = new ast::AddressExpr{ location, args.back() }; }
-					return new ast::UntypedExpr{ 
+					return new ast::UntypedExpr{
 						location, new ast::NameExpr{ location, "?=?" }, std::move(args) };
 				} else {
-					return new ast::UntypedExpr{ 
+					return new ast::UntypedExpr{
 						location, new ast::NameExpr{ location, fname }, std::move(args) };
 				}
@@ -498,5 +499,5 @@
 		struct MassAssignMatcher final : public Matcher {
 			MassAssignMatcher(
-				TupleAssignSpotter_new & s, const CodeLocation & loc, 
+				TupleAssignSpotter_new & s, const CodeLocation & loc,
 				const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r )
 			: Matcher( s, loc, l, r ) {}
@@ -508,10 +509,10 @@
 				assert( lhs.empty() ? rhs.empty() : rhs.size() <= 1 );
 
-				ast::ptr< ast::ObjectDecl > rtmp = 
+				ast::ptr< ast::ObjectDecl > rtmp =
 					rhs.size() == 1 ? newObject( rhsNamer, rhs.front()->expr ) : nullptr;
 
 				std::vector< ast::ptr< ast::Expr > > out;
 				for ( ResolvExpr::CandidateRef & lhsCand : lhs ) {
-					// create a temporary object for each value in the LHS and create a call 
+					// create a temporary object for each value in the LHS and create a call
 					// involving the RHS
 					ast::ptr< ast::ObjectDecl > ltmp = newObject( lhsNamer, lhsCand->expr );
@@ -528,5 +529,5 @@
 		struct MultipleAssignMatcher final : public Matcher {
 			MultipleAssignMatcher(
-				TupleAssignSpotter_new & s, const CodeLocation & loc, 
+				TupleAssignSpotter_new & s, const CodeLocation & loc,
 				const ResolvExpr::CandidateList & l, const ResolvExpr::CandidateList & r )
 			: Matcher( s, loc, l, r ) {}
@@ -538,5 +539,5 @@
 				if ( lhs.size() != rhs.size() ) return {};
 
-				// produce a new temporary object for each value in the LHS and RHS and pairwise 
+				// produce a new temporary object for each value in the LHS and RHS and pairwise
 				// create the calls
 				std::vector< ast::ptr< ast::ObjectDecl > > ltmp, rtmp;
@@ -547,5 +548,5 @@
 					ResolvExpr::CandidateRef & rhsCand = rhs[i];
 
-					// convert RHS to LHS type minus one reference -- important for case where LHS 
+					// convert RHS to LHS type minus one reference -- important for case where LHS
 					// is && and RHS is lvalue
 					auto lhsType = lhsCand->expr->result.strict_as< ast::ReferenceType >();
@@ -557,5 +558,5 @@
 					rtmp.emplace_back( std::move( robj ) );
 
-					// resolve the cast expression so that rhsCand return type is bound by the cast 
+					// resolve the cast expression so that rhsCand return type is bound by the cast
 					// type as needed, and transfer the resulting environment
 					ResolvExpr::CandidateFinder finder{ spotter.crntFinder.symtab, env };
@@ -564,8 +565,8 @@
 					env = std::move( finder.candidates.front()->env );
 				}
-				
+
 				splice( tmpDecls, ltmp );
 				splice( tmpDecls, rtmp );
-				
+
 				return out;
 			}
@@ -575,12 +576,12 @@
 		std::string fname;
 		std::unique_ptr< Matcher > matcher;
-	
+
 	public:
-		TupleAssignSpotter_new( ResolvExpr::CandidateFinder & f ) 
+		TupleAssignSpotter_new( ResolvExpr::CandidateFinder & f )
 		: crntFinder( f ), fname(), matcher() {}
 
 		// find left- and right-hand-sides for mass or multiple assignment
-		void spot( 
-			const ast::UntypedExpr * expr, std::vector< ResolvExpr::CandidateFinder > & args 
+		void spot(
+			const ast::UntypedExpr * expr, std::vector< ResolvExpr::CandidateFinder > & args
 		) {
 			if ( auto op = expr->func.as< ast::NameExpr >() ) {
@@ -599,8 +600,8 @@
 					if ( ! refToTuple( lhsCand->expr ) ) continue;
 
-					// explode is aware of casts - ensure every LHS is sent into explode with a 
+					// explode is aware of casts - ensure every LHS is sent into explode with a
 					// reference cast
 					if ( ! lhsCand->expr.as< ast::CastExpr >() ) {
-						lhsCand->expr = new ast::CastExpr{ 
+						lhsCand->expr = new ast::CastExpr{
 							lhsCand->expr, new ast::ReferenceType{ lhsCand->expr->result } };
 					}
@@ -610,5 +611,5 @@
 					explode( *lhsCand, crntFinder.symtab, back_inserter(lhs), true );
 					for ( ResolvExpr::CandidateRef & cand : lhs ) {
-						// each LHS value must be a reference - some come in with a cast, if not 
+						// each LHS value must be a reference - some come in with a cast, if not
 						// just cast to reference here
 						if ( ! cand->expr->result.as< ast::ReferenceType >() ) {
@@ -629,10 +630,10 @@
 								// multiple assignment
 								explode( *rhsCand, crntFinder.symtab, back_inserter(rhs), true );
-								matcher.reset( 
+								matcher.reset(
 									new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
 							} else {
 								// mass assignment
 								rhs.emplace_back( rhsCand );
-								matcher.reset( 
+								matcher.reset(
 									new MassAssignMatcher{ *this, expr->location, lhs, rhs } );
 							}
@@ -642,5 +643,5 @@
 						// expand all possible RHS possibilities
 						std::vector< ResolvExpr::CandidateList > rhsCands;
-						combos( 
+						combos(
 							std::next( args.begin(), 1 ), args.end(), back_inserter( rhsCands ) );
 						for ( const ResolvExpr::CandidateList & rhsCand : rhsCands ) {
@@ -648,5 +649,5 @@
 							ResolvExpr::CandidateList rhs;
 							explode( rhsCand, crntFinder.symtab, back_inserter(rhs), true );
-							matcher.reset( 
+							matcher.reset(
 								new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
 							match();
@@ -663,6 +664,6 @@
 
 			if ( ! ( matcher->lhs.empty() && matcher->rhs.empty() ) ) {
-				// if both LHS and RHS are empty than this is the empty tuple case, wherein it's 
-				// okay for newAssigns to be empty. Otherwise, return early so that no new 
+				// if both LHS and RHS are empty than this is the empty tuple case, wherein it's
+				// okay for newAssigns to be empty. Otherwise, return early so that no new
 				// candidates are generated
 				if ( newAssigns.empty() ) return;
@@ -692,5 +693,5 @@
 			}
 
-			// extract expressions from the assignment candidates to produce a list of assignments 
+			// extract expressions from the assignment candidates to produce a list of assignments
 			// that together form a sigle candidate
 			std::vector< ast::ptr< ast::Expr > > solved;
@@ -701,7 +702,7 @@
 
 			crntFinder.candidates.emplace_back( std::make_shared< ResolvExpr::Candidate >(
-				new ast::TupleAssignExpr{ 
-					matcher->location, std::move( solved ), std::move( matcher->tmpDecls ) }, 
-				std::move( matcher->env ), std::move( matcher->open ), std::move( matcher->need ), 
+				new ast::TupleAssignExpr{
+					matcher->location, std::move( solved ), std::move( matcher->tmpDecls ) },
+				std::move( matcher->env ), std::move( matcher->open ), std::move( matcher->need ),
 				ResolvExpr::sumCost( crnt ) + matcher->baseCost ) );
 		}
@@ -709,6 +710,6 @@
 } // anonymous namespace
 
-void handleTupleAssignment( 
-	ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign, 
+void handleTupleAssignment(
+	ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign,
 	std::vector< ResolvExpr::CandidateFinder > & args
 ) {
