Index: src/GenPoly/Specialize.cc
===================================================================
--- src/GenPoly/Specialize.cc	(revision be9288a525b285ac5a849a870863a162fd3d36c7)
+++ src/GenPoly/Specialize.cc	(revision bd098eaec62bec74469554f5b20132dc02a69871)
@@ -101,4 +101,26 @@
 	}
 
+	// walk into tuple type and find the number of components
+	size_t singleParameterSize( Type * type ) {
+		if ( TupleType * tt = dynamic_cast< TupleType * >( type ) ) {
+			size_t sz = 0;
+			for ( Type * t : *tt ) {
+				sz += singleParameterSize( t );
+			}
+			return sz;
+		} else {
+			return 1;
+		}
+	}
+
+	// find the total number of components in a parameter list
+	size_t functionParameterSize( FunctionType * ftype ) {
+		size_t sz = 0;
+		for ( DeclarationWithType * p : ftype->get_parameters() ) {
+			sz += singleParameterSize( p->get_type() );
+		}
+		return sz;
+	}
+
 	bool needsTupleSpecialization( Type *formalType, Type *actualType ) {
 		// Needs tuple specialization if the structure of the formal type and actual type do not match.
@@ -111,5 +133,9 @@
 			FunctionType * aftype = getFunctionType( actualType );
 			assertf( aftype, "formal type is a function type, but actual type is not." );
+			// Can't tuple specialize if parameter sizes deeply-differ.
+			if ( functionParameterSize( fftype ) != functionParameterSize( aftype ) ) return false;
+			// tuple-parameter sizes are the same, but actual parameter sizes differ - must tuple specialize
 			if ( fftype->get_parameters().size() != aftype->get_parameters().size() ) return true;
+			// total parameter size can be the same, while individual parameters can have different structure
 			for ( auto params : group_iterate( fftype->get_parameters(), aftype->get_parameters() ) ) {
 				DeclarationWithType * formal = std::get<0>(params);
