Skip to content

Commit d0cef92

Browse files
stereotype441commit-bot@chromium.org
authored andcommitted
Migration: refactor logic to match up type parameters between function types.
This logic will need to be re-used in the EdgeBuilder. Change-Id: I042560683903408936b5cfd0910c90ec965cd70e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/122306 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Paul Berry <paulberry@google.com>
1 parent 15ec4a3 commit d0cef92

File tree

1 file changed

+109
-64
lines changed

1 file changed

+109
-64
lines changed

pkg/nnbd_migration/lib/src/decorated_type.dart

Lines changed: 109 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)