Index: src/InitTweak/GenInit.cc
===================================================================
--- src/InitTweak/GenInit.cc	(revision 65660bd065cbc0b68c92db2425b5984d675dff58)
+++ src/InitTweak/GenInit.cc	(revision ac9ca967fc4b0004f809382a113690d4c01cae00)
@@ -238,4 +238,10 @@
 
 	bool CtorDtor::isManaged( Type * type ) const {
+		if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) {
+			// tuple is also managed if any of its components are managed
+			if ( std::any_of( tupleType->get_types().begin(), tupleType->get_types().end(), [&](Type * type) { return isManaged( type ); }) ) {
+				return true;
+			}
+		}
 		return managedTypes.find( SymTab::Mangler::mangle( type ) ) != managedTypes.end();
 	}
@@ -245,7 +251,4 @@
 		while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
 			type = at->get_base();
-		}
-		if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) {
-			return std::any_of( tupleType->get_types().begin(), tupleType->get_types().end(), [&](Type * type) { return isManaged( type ); });
 		}
 		return isManaged( type );
Index: src/ResolvExpr/AlternativeFinder.cc
===================================================================
--- src/ResolvExpr/AlternativeFinder.cc	(revision 65660bd065cbc0b68c92db2425b5984d675dff58)
+++ src/ResolvExpr/AlternativeFinder.cc	(revision ac9ca967fc4b0004f809382a113690d4c01cae00)
@@ -138,11 +138,4 @@
 		}
 
-		template< typename InputIterator >
-		void simpleCombineEnvironments( InputIterator begin, InputIterator end, TypeEnvironment &result ) {
-			while ( begin != end ) {
-				result.simpleCombine( (*begin++).env );
-			}
-		}
-
 		void renameTypes( Expression *expr ) {
 			expr->get_result()->accept( global_renamer );
@@ -216,27 +209,23 @@
 	template< typename StructOrUnionType >
 	void AlternativeFinder::addAggMembers( StructOrUnionType *aggInst, Expression *expr, const Cost &newCost, const TypeEnvironment & env, Expression * member ) {
-
-		// // member must be either a tuple expression or a name expr
-		// if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( memberExpr->get_member() ) ) {
-		//  addAggMembers( structInst, agg->expr, agg->cost, nameExpr->get_name() );
-		// } else {
-		//  TupleExpr * tupleExpr = safe_dynamic_cast< TupleExpr * >( memberExpr->get_member() );
-		//  // xxx - ...
-		//  assert( false );
-		// }
-		// if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( memberExpr->get_member() ) ) {
-
-		// }
-		NameExpr * nameExpr = safe_dynamic_cast< NameExpr * >( member );
-		const std::string & name = nameExpr->get_name();
-		std::list< Declaration* > members;
-		aggInst->lookup( name, members );
-		for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
-			if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
-				alternatives.push_back( Alternative( new MemberExpr( dwt, expr->clone() ), env, newCost ) );
-				renameTypes( alternatives.back().expr );
-			} else {
-				assert( false );
-			}
+		// member must be either a tuple expression or a name expr
+		if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( member ) ) {
+			const std::string & name = nameExpr->get_name();
+			std::list< Declaration* > members;
+			aggInst->lookup( name, members );
+			for ( std::list< Declaration* >::const_iterator i = members.begin(); i != members.end(); ++i ) {
+				if ( DeclarationWithType *dwt = dynamic_cast< DeclarationWithType* >( *i ) ) {
+					alternatives.push_back( Alternative( new MemberExpr( dwt, expr->clone() ), env, newCost ) );
+					renameTypes( alternatives.back().expr );
+				} else {
+					assert( false );
+				}
+			}
+		} else if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( member ) ) {
+			assert( false );
+		} else {
+			// xxx - temporary
+			std::cerr << member << std::endl;
+			assertf( false, "reached unexpected case of addAggMembers" );
 		}
 	}
Index: src/ResolvExpr/AlternativeFinder.h
===================================================================
--- src/ResolvExpr/AlternativeFinder.h	(revision 65660bd065cbc0b68c92db2425b5984d675dff58)
+++ src/ResolvExpr/AlternativeFinder.h	(revision ac9ca967fc4b0004f809382a113690d4c01cae00)
@@ -113,4 +113,11 @@
 
 	Cost sumCost( const AltList &in );
+
+	template< typename InputIterator >
+	void simpleCombineEnvironments( InputIterator begin, InputIterator end, TypeEnvironment &result ) {
+		while ( begin != end ) {
+			result.simpleCombine( (*begin++).env );
+		}
+	}
 } // namespace ResolvExpr
 
Index: src/Tuples/TupleAssignment.cc
===================================================================
--- src/Tuples/TupleAssignment.cc	(revision 65660bd065cbc0b68c92db2425b5984d675dff58)
+++ src/Tuples/TupleAssignment.cc	(revision ac9ca967fc4b0004f809382a113690d4c01cae00)
@@ -142,5 +142,9 @@
 		for ( std::list< Expression * >::iterator i = new_assigns.begin(); i != new_assigns.end(); ++i ) {
 			ResolvExpr::AlternativeFinder finder( currentFinder.get_indexer(), currentFinder.get_environ() );
-			finder.findWithAdjustment(*i);
+			try {
+				finder.findWithAdjustment(*i);
+			} catch (...) {
+				return; // xxx - no match should not mean failure, it just means this particular tuple assignment isn't valid
+			}
 			// prune expressions that don't coincide with
 			ResolvExpr::AltList alts = finder.get_alternatives();
@@ -157,7 +161,7 @@
 		}
 		// xxx - need to do this??
-		// TypeEnvironment compositeEnv;
-		// simpleCombineEnvironments( i->begin(), i->end(), compositeEnv );
-		currentFinder.get_alternatives().push_front( ResolvExpr::Alternative(new TupleAssignExpr(solved_assigns, matcher->tmpDecls), currentFinder.get_environ(), ResolvExpr::sumCost( current ) ) );
+		ResolvExpr::TypeEnvironment compositeEnv;
+		simpleCombineEnvironments( current.begin(), current.end(), compositeEnv );
+		currentFinder.get_alternatives().push_front( ResolvExpr::Alternative(new TupleAssignExpr(solved_assigns, matcher->tmpDecls), compositeEnv, ResolvExpr::sumCost( current ) ) );
 	}
 
