@@ -245,54 +245,15 @@ class DecoratedType implements DecoratedTypeInfo {
245245 if (thisType.typeFormals.length != otherType.typeFormals.length) {
246246 return false ;
247247 }
248- var thisReturnType = this .returnType;
249- var otherReturnType = other.returnType;
250- var thisPositionalParameters = this .positionalParameters;
251- var otherPositionalParameters = other.positionalParameters;
252- var thisNamedParameters = this .namedParameters;
253- var otherNamedParameters = other.namedParameters;
254- if (! _compareTypeFormalLists (
255- thisType.typeFormals, otherType.typeFormals)) {
256- // Create a fresh set of type variables and substitute so we can
257- // compare safely.
258- var thisSubstitution = < TypeParameterElement , DecoratedType > {};
259- var otherSubstitution = < TypeParameterElement , DecoratedType > {};
260- var newParameters = < TypeParameterElement > [];
261- for (int i = 0 ; i < thisType.typeFormals.length; i++ ) {
262- var newParameter = TypeParameterElementImpl .synthetic (
263- thisType.typeFormals[i].name);
264- newParameters.add (newParameter);
265- var newParameterType =
266- DecoratedType ._forTypeParameterSubstitution (newParameter);
267- thisSubstitution[thisType.typeFormals[i]] = newParameterType;
268- otherSubstitution[otherType.typeFormals[i]] = newParameterType;
269- }
270- for (int i = 0 ; i < thisType.typeFormals.length; i++ ) {
271- var thisBound =
272- this .typeFormalBounds[i].substitute (thisSubstitution);
273- var otherBound =
274- other.typeFormalBounds[i].substitute (otherSubstitution);
275- if (thisBound != otherBound) return false ;
276- recordTypeParameterBound (newParameters[i], thisBound);
277- }
278- // TODO(paulberry): need to substitute bounds and compare them.
279- thisReturnType = thisReturnType.substitute (thisSubstitution);
280- otherReturnType = otherReturnType.substitute (otherSubstitution);
281- thisPositionalParameters =
282- _substituteList (thisPositionalParameters, thisSubstitution);
283- otherPositionalParameters =
284- _substituteList (otherPositionalParameters, otherSubstitution);
285- thisNamedParameters =
286- _substituteMap (thisNamedParameters, thisSubstitution);
287- otherNamedParameters =
288- _substituteMap (otherNamedParameters, otherSubstitution);
289- }
290- if (thisReturnType != otherReturnType) return false ;
248+ var renamed = RenamedDecoratedFunctionTypes .match (
249+ this , other, (bound1, bound2) => bound1 == bound2);
250+ if (renamed == null ) return false ;
251+ if (renamed.returnType1 != renamed.returnType2) return false ;
291252 if (! _compareLists (
292- thisPositionalParameters, otherPositionalParameters )) {
253+ renamed.positionalParameters1, renamed.positionalParameters2 )) {
293254 return false ;
294255 }
295- if (! _compareMaps (thisNamedParameters, otherNamedParameters )) {
256+ if (! _compareMaps (renamed.namedParameters1, renamed.namedParameters2 )) {
296257 return false ;
297258 }
298259 return true ;
@@ -566,20 +527,6 @@ class DecoratedType implements DecoratedTypeInfo {
566527 namedParameters: newNamedParameters);
567528 }
568529
569- List <DecoratedType > _substituteList (List <DecoratedType > list,
570- Map <TypeParameterElement , DecoratedType > substitution) {
571- return list.map ((t) => t.substitute (substitution)).toList ();
572- }
573-
574- Map <String , DecoratedType > _substituteMap (Map <String , DecoratedType > map,
575- Map <TypeParameterElement , DecoratedType > substitution) {
576- var result = < String , DecoratedType > {};
577- for (var entry in map.entries) {
578- result[entry.key] = entry.value.substitute (substitution);
579- }
580- return result;
581- }
582-
583530 /// Retrieves the decorated bound of the given [typeParameter] .
584531 ///
585532 /// [typeParameter] must have an enclosing element of `null` . Type parameters
@@ -621,14 +568,112 @@ class DecoratedType implements DecoratedTypeInfo {
621568 }
622569 return true ;
623570 }
571+ }
572+
573+ /// Helper class that renames the type parameters in two decorated function
574+ /// types so that they match.
575+ class RenamedDecoratedFunctionTypes {
576+ final DecoratedType returnType1;
577+
578+ final DecoratedType returnType2;
579+
580+ final List <DecoratedType > positionalParameters1;
581+
582+ final List <DecoratedType > positionalParameters2;
583+
584+ final Map <String , DecoratedType > namedParameters1;
585+
586+ final Map <String , DecoratedType > namedParameters2;
587+
588+ RenamedDecoratedFunctionTypes ._(
589+ this .returnType1,
590+ this .returnType2,
591+ this .positionalParameters1,
592+ this .positionalParameters2,
593+ this .namedParameters1,
594+ this .namedParameters2);
595+
596+ /// Attempt to find a renaming of the type parameters of [type1] and [type2]
597+ /// (both of which should be function types) such that the generic type
598+ /// parameters match.
599+ ///
600+ /// The callback [boundsMatcher] is used to determine whether type parameter
601+ /// bounds match.
602+ ///
603+ /// If such a renaming can be found, it is returned. If not, `null` is
604+ /// returned.
605+ static RenamedDecoratedFunctionTypes match (
606+ DecoratedType type1,
607+ DecoratedType type2,
608+ bool Function (DecoratedType , DecoratedType ) boundsMatcher) {
609+ if (! _isNeeded (type1.typeFormals, type2.typeFormals)) {
610+ return RenamedDecoratedFunctionTypes ._(
611+ type1.returnType,
612+ type2.returnType,
613+ type1.positionalParameters,
614+ type2.positionalParameters,
615+ type1.namedParameters,
616+ type2.namedParameters);
617+ }
618+ // Create a fresh set of type variables and substitute so we can
619+ // compare safely.
620+ var substitution1 = < TypeParameterElement , DecoratedType > {};
621+ var substitution2 = < TypeParameterElement , DecoratedType > {};
622+ var newParameters = < TypeParameterElement > [];
623+ for (int i = 0 ; i < type1.typeFormals.length; i++ ) {
624+ var newParameter =
625+ TypeParameterElementImpl .synthetic (type1.typeFormals[i].name);
626+ newParameters.add (newParameter);
627+ var newParameterType =
628+ DecoratedType ._forTypeParameterSubstitution (newParameter);
629+ substitution1[type1.typeFormals[i]] = newParameterType;
630+ substitution2[type2.typeFormals[i]] = newParameterType;
631+ }
632+ for (int i = 0 ; i < type1.typeFormals.length; i++ ) {
633+ var bound1 = type1.typeFormalBounds[i].substitute (substitution1);
634+ var bound2 = type2.typeFormalBounds[i].substitute (substitution2);
635+ if (! boundsMatcher (bound1, bound2)) return null ;
636+ DecoratedType .recordTypeParameterBound (newParameters[i], bound1);
637+ }
638+ var returnType1 = type1.returnType.substitute (substitution1);
639+ var returnType2 = type2.returnType.substitute (substitution2);
640+ var positionalParameters1 =
641+ _substituteList (type1.positionalParameters, substitution1);
642+ var positionalParameters2 =
643+ _substituteList (type2.positionalParameters, substitution2);
644+ var namedParameters1 = _substituteMap (type1.namedParameters, substitution1);
645+ var namedParameters2 = _substituteMap (type2.namedParameters, substitution2);
646+ return RenamedDecoratedFunctionTypes ._(
647+ returnType1,
648+ returnType2,
649+ positionalParameters1,
650+ positionalParameters2,
651+ namedParameters1,
652+ namedParameters2);
653+ }
624654
625- static bool _compareTypeFormalLists (List <TypeParameterElement > formals1,
655+ static bool _isNeeded (List <TypeParameterElement > formals1,
626656 List <TypeParameterElement > formals2) {
627- if (identical (formals1, formals2)) return true ;
628- if (formals1.length != formals2.length) return false ;
657+ if (identical (formals1, formals2)) return false ;
658+ if (formals1.length != formals2.length) return true ;
629659 for (int i = 0 ; i < formals1.length; i++ ) {
630- if (! identical (formals1[i], formals2[i])) return false ;
660+ if (! identical (formals1[i], formals2[i])) return true ;
631661 }
632- return true ;
662+ return false ;
663+ }
664+
665+ static List <DecoratedType > _substituteList (List <DecoratedType > list,
666+ Map <TypeParameterElement , DecoratedType > substitution) {
667+ return list.map ((t) => t.substitute (substitution)).toList ();
668+ }
669+
670+ static Map <String , DecoratedType > _substituteMap (
671+ Map <String , DecoratedType > map,
672+ Map <TypeParameterElement , DecoratedType > substitution) {
673+ var result = < String , DecoratedType > {};
674+ for (var entry in map.entries) {
675+ result[entry.key] = entry.value.substitute (substitution);
676+ }
677+ return result;
633678 }
634679}
0 commit comments