Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 906e24deeab82aafdd4cbb08fb896c8ffe5b99e0)
+++ src/InitTweak/FixInit.cc	(revision 1132b62939ee72e624dd65d3bacb0e67cb1a0347)
@@ -70,6 +70,9 @@
 			/// create and resolve ctor/dtor expression: fname(var, [cpArg])
 			ApplicationExpr * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL );
+			ApplicationExpr * makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg = NULL );
 			/// true if type does not need to be copy constructed to ensure correctness
-			bool skipCopyConstruct( Type * );
+			bool skipCopyConstruct( Type * type );
+			void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr );
+			void destructRet( Expression * ret, ImplicitCopyCtorExpr * impCpCtorExpr );
 		private:
 			TypeSubstitution * env;
@@ -359,6 +362,11 @@
 		ApplicationExpr * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) {
 			assert( var );
+			return makeCtorDtor( fname, new AddressExpr( new VariableExpr( var ) ), cpArg );
+		}
+
+		ApplicationExpr * ResolveCopyCtors::makeCtorDtor( const std::string & fname, Expression * thisArg, Expression * cpArg ) {
+			assert( thisArg );
 			UntypedExpr * untyped = new UntypedExpr( new NameExpr( fname ) );
-			untyped->get_args().push_back( new AddressExpr( new VariableExpr( var ) ) );
+			untyped->get_args().push_back( thisArg );
 			if (cpArg) untyped->get_args().push_back( cpArg->clone() );
 
@@ -377,8 +385,53 @@
 		}
 
+		void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ) {
+			static UniqueName tempNamer("_tmp_cp");
+			CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *impCpCtorExpr->get_env() << std::endl; )
+			assert( arg->has_result() );
+			Type * result = arg->get_result();
+			if ( skipCopyConstruct( result ) ) return; // skip certain non-copyable types
+
+			if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( arg ) ) {
+				for ( Expression * & expr : tupleExpr->get_exprs() ) {
+					copyConstructArg( expr, impCpCtorExpr );
+				}
+				return;
+			}
+
+			// type may involve type variables, so apply type substitution to get temporary variable's actual type
+			result = result->clone();
+			impCpCtorExpr->get_env()->apply( result );
+			ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 );
+			tmp->get_type()->set_isConst( false );
+
+			// create and resolve copy constructor
+			CP_CTOR_PRINT( std::cerr << "makeCtorDtor for an argument" << std::endl; )
+			ApplicationExpr * cpCtor = makeCtorDtor( "?{}", tmp, arg );
+
+			// if the chosen constructor is intrinsic, the copy is unnecessary, so
+			// don't create the temporary and don't call the copy constructor
+			VariableExpr * function = dynamic_cast< VariableExpr * >( cpCtor->get_function() );
+			assert( function );
+			if ( function->get_var()->get_linkage() != LinkageSpec::Intrinsic ) {
+				// replace argument to function call with temporary
+				arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) );
+				impCpCtorExpr->get_tempDecls().push_back( tmp );
+				impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );
+			} // if
+		}
+
+		void ResolveCopyCtors::destructRet( Expression * ret, ImplicitCopyCtorExpr * impCpCtorExpr ) {
+			if ( TupleType * tupleType = dynamic_cast< TupleType * > ( ret->get_result() ) ) {
+				int idx = 0;
+				for ( Type *& t : tupleType->get_types() ) {
+					(void)t;
+					destructRet( new TupleIndexExpr( ret->clone(), idx++ ), impCpCtorExpr );
+				}
+				return;
+			}
+			impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", new AddressExpr( ret ) ) );
+		}
+
 		void ResolveCopyCtors::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) {
-			static UniqueName tempNamer("_tmp_cp");
-			static UniqueName retNamer("_tmp_cp_ret");
-
 			CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; )
 			Visitor::visit( impCpCtorExpr );
@@ -389,29 +442,5 @@
 			// take each argument and attempt to copy construct it.
 			for ( Expression * & arg : appExpr->get_args() ) {
-				CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *impCpCtorExpr->get_env() << std::endl; )
-				// xxx - need to handle tuple arguments
-				assert( arg->has_result() );
-				Type * result = arg->get_result();
-				if ( skipCopyConstruct( result ) ) continue; // skip certain non-copyable types
-				// type may involve type variables, so apply type substitution to get temporary variable's actual type
-				result = result->clone();
-				impCpCtorExpr->get_env()->apply( result );
-				ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 );
-				tmp->get_type()->set_isConst( false );
-
-				// create and resolve copy constructor
-				CP_CTOR_PRINT( std::cerr << "makeCtorDtor for an argument" << std::endl; )
-				ApplicationExpr * cpCtor = makeCtorDtor( "?{}", tmp, arg );
-
-				// if the chosen constructor is intrinsic, the copy is unnecessary, so
-				// don't create the temporary and don't call the copy constructor
-				VariableExpr * function = dynamic_cast< VariableExpr * >( cpCtor->get_function() );
-				assert( function );
-				if ( function->get_var()->get_linkage() != LinkageSpec::Intrinsic ) {
-					// replace argument to function call with temporary
-					arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) );
-					impCpCtorExpr->get_tempDecls().push_back( tmp );
-					impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );
-				} // if
+				copyConstructArg( arg, impCpCtorExpr );
 			} // for
 
@@ -425,5 +454,5 @@
 			Type * result = appExpr->get_result();
 			if ( ! result->isVoid() ) {
-				// need to flatten result type and construct each
+				static UniqueName retNamer("_tmp_cp_ret");
 				result = result->clone();
 				impCpCtorExpr->get_env()->apply( result );
@@ -432,5 +461,5 @@
 				impCpCtorExpr->get_returnDecls().push_back( ret );
 				CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
-				impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) );
+				destructRet( new VariableExpr( ret ) , impCpCtorExpr );
 			} // for
 			CP_CTOR_PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; )
