Fix NullabilityEliminator to substitute type parameters in bounds.

R=brianwilkerson@google.com, paulberry@google.com

Change-Id: I9b3d986a52f8006854b23db600493566aea86cb9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/135527
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
This commit is contained in:
Konstantin Shcheglov 2020-02-12 22:08:27 +00:00 committed by commit-bot@chromium.org
parent 0966e06ee4
commit 84ff9e5008
4 changed files with 50 additions and 2 deletions

View file

@ -359,10 +359,13 @@ class ElementDisplayStringBuilder {
if (type is TypeParameterType) {
referencedTypeParameters.add(type.element);
} else if (type is FunctionType) {
collectTypeParameters(type.returnType);
for (var typeParameter in type.typeFormals) {
collectTypeParameters(typeParameter.bound);
}
for (var parameter in type.parameters) {
collectTypeParameters(parameter.type);
}
collectTypeParameters(type.returnType);
} else if (type is InterfaceType) {
for (var typeArgument in type.typeArguments) {
collectTypeParameters(typeArgument);

View file

@ -137,6 +137,7 @@ class NullabilityEliminator extends DartTypeVisitor<DartType> {
}
var freshElements = List<TypeParameterElement>(elements.length);
var substitutionMap = <TypeParameterElement, TypeParameterType>{};
for (var i = 0; i < elements.length; i++) {
// TODO (kallentu) : Clean up TypeParameterElementImpl casting once
// variance is added to the interface.
@ -145,8 +146,19 @@ class NullabilityEliminator extends DartTypeVisitor<DartType> {
if (!element.isLegacyCovariant) {
freshElement.variance = element.variance;
}
freshElement.bound = freshBounds[i];
freshElements[i] = freshElement;
substitutionMap[element] = freshElement.instantiate(
nullabilitySuffix: NullabilitySuffix.none,
);
}
var substitution = Substitution.fromMap(substitutionMap);
for (var i = 0; i < elements.length; i++) {
var bound = freshBounds[i];
if (bound != null) {
var freshElement = freshElements[i] as TypeParameterElementImpl;
freshElement.bound = substitution.substituteType(bound);
}
}
FunctionType newType = replaceTypeParameters(type, freshElements);

View file

@ -207,6 +207,20 @@ class NullabilityEliminatorTest with ElementsTypesMixin {
);
}
test_functionType_typeParameters_bound_other() {
var T = typeParameter('T', bound: intNone);
var U = typeParameter('U', bound: typeParameterTypeNone(T));
_verifyStr(
functionTypeNone(
typeFormals: [T, U],
returnType: typeParameterTypeNone(T),
),
'T Function<T extends int, U extends T>()',
'T* Function<T extends int*, U extends T*>()*',
);
}
test_functionType_typeParameters_bound_question() {
var T = typeParameter('T', bound: intQuestion);

View file

@ -431,6 +431,25 @@ class A<X extends int> {}
import 'a.dart';
class A1<T extends Null> extends A<T> {}
''');
}
test_extends_optIn_fromOptOut_otherTypeParameter() async {
newFile('/test/lib/a.dart', content: r'''
void foo<T extends U, U>() {
}
''');
await assertNoErrorsInCode(r'''
// @dart=2.6
import 'a.dart';
class A {}
class B extends A {}
main() {
foo<B, A>();
}
''');
}
}