Index: src/InitTweak/FixInit.cc
===================================================================
--- src/InitTweak/FixInit.cc	(revision 96fc67b1d78be4a46077b51a6bbc0f0547cbf5f5)
+++ src/InitTweak/FixInit.cc	(revision 20eacb74465532b7924bf06b89d257a794c9c405)
@@ -653,7 +653,16 @@
 		}
 
-		DeclarationWithType * getDtorFunc( ObjectDecl * objDecl, Statement * dtor, std::list< Statement * > & stmtsToAdd ) {
+		DeclarationWithType * getDtorFunc( ObjectDecl * objDecl, Statement * input, std::list< Statement * > & stmtsToAdd ) {
+			// unwrap implicit statement wrapper
+			assert( dtor );
+			std::list< Expression * > matches;
+			collectCtorDtorCalls( dtor, matches );
+
 			if ( dynamic_cast< ExprStmt * >( dtor ) ) {
-				if ( DeclarationWithType * func = getFunction( getCtorDtorCall( dtor ) ) ) {
+				// only one destructor call in the expression
+				if ( matches.size() == 1 ) {
+					DeclarationWithType * func = getFunction( matches.front() );
+					assertf( func, "getFunction failed to find function in %s", toString( matches.front() ).c_str() );
+
 					// cleanup argument must be a function, not an object (including function pointer)
 					if ( FunctionDecl * dtorFunc = dynamic_cast< FunctionDecl * > ( func ) ) {
@@ -677,7 +686,9 @@
 			ObjectDecl * thisParam = getParamThis( dtorFunc->type );
 			Expression * replacement = new VariableExpr( thisParam );
-			if ( ArrayType * at = dynamic_cast< ArrayType * >( replacement->result->stripReferences() ) ) {
+
+			Type * base = replacement->result->stripReferences();
+			if ( dynamic_cast< ArrayType * >( base ) || dynamic_cast< TupleType * > ( base ) ) {
 				// need to cast away reference for array types, since the destructor is generated without the reference type
-				replacement = new CastExpr( replacement, at->clone() );
+				replacement = new CastExpr( replacement, base->clone() );
 			}
 			VarExprReplacer::replace( dtor, { std::make_pair( objDecl, replacement ) } );
@@ -804,4 +815,5 @@
 							ImplicitCtorDtorStmt * implicit = strict_dynamic_cast< ImplicitCtorDtorStmt * >( dtor );
 							Statement * dtorStmt = implicit->callStmt;
+
 							// don't need to call intrinsic dtor, because it does nothing, but
 							// non-intrinsic dtors must be called
@@ -810,5 +822,4 @@
 								DeclarationWithType * dtorFunc = getDtorFunc( objDecl, dtorStmt, stmtsToAddBefore );
 								objDecl->attributes.push_back( new Attribute( "cleanup", { new VariableExpr( dtorFunc ) } ) );
-								// objDecl->attributes.push_back( new Attribute( "cleanup", { new NameExpr( dtorFunc->name ) } ) );
 								ctorInit->dtor = nullptr;
 							} // if
Index: src/InitTweak/InitTweak.cc
===================================================================
--- src/InitTweak/InitTweak.cc	(revision 96fc67b1d78be4a46077b51a6bbc0f0547cbf5f5)
+++ src/InitTweak/InitTweak.cc	(revision 20eacb74465532b7924bf06b89d257a794c9c405)
@@ -343,5 +343,5 @@
 		std::list< Expression * > matches;
 		collectCtorDtorCalls( stmt, matches );
-		assert( matches.size() <= 1 );
+		assertf( matches.size() <= 1, "%zd constructor/destructors found in %s", matches.size(), toString( stmt ).c_str() );
 		return matches.size() == 1 ? matches.front() : nullptr;
 	}
