Fix resolveToBound for nullability
Change-Id: I510c349251588356677d52574f259706ec2047e0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103183
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Mike Fairhurst <mfairhurst@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index ec7f129..81f079e 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -3181,7 +3181,21 @@
return objectType;
}
- return element.bound.resolveToBound(objectType);
+ NullabilitySuffix newNullabilitySuffix;
+ if (nullabilitySuffix == NullabilitySuffix.question ||
+ (element.bound as TypeImpl).nullabilitySuffix ==
+ NullabilitySuffix.question) {
+ newNullabilitySuffix = NullabilitySuffix.question;
+ } else if (nullabilitySuffix == NullabilitySuffix.star ||
+ (element.bound as TypeImpl).nullabilitySuffix ==
+ NullabilitySuffix.star) {
+ newNullabilitySuffix = NullabilitySuffix.star;
+ } else {
+ newNullabilitySuffix = NullabilitySuffix.none;
+ }
+
+ return (element.bound.resolveToBound(objectType) as TypeImpl)
+ .withNullability(newNullabilitySuffix);
}
@override
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index bc41dcb..e9b7bf1 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -3844,6 +3844,88 @@
expect(type.resolveToBound(null), same(classS.type));
}
+ void test_resolveToBound_bound_nullableInner() {
+ ClassElementImpl classS = ElementFactory.classElement2("A");
+ TypeParameterElementImpl element =
+ new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+ element.bound =
+ (classS.type as TypeImpl).withNullability(NullabilitySuffix.question);
+ TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
+ expect(type.resolveToBound(null), same(element.bound));
+ }
+
+ void test_resolveToBound_bound_nullableInnerOuter() {
+ ClassElementImpl classS = ElementFactory.classElement2("A");
+ TypeParameterElementImpl element =
+ new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+ element.bound =
+ (classS.type as TypeImpl).withNullability(NullabilitySuffix.question);
+ TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+ .withNullability(NullabilitySuffix.question);
+ expect(type.resolveToBound(null), same(element.bound));
+ }
+
+ void test_resolveToBound_bound_nullableInnerStarOuter() {
+ ClassElementImpl classS = ElementFactory.classElement2("A");
+ TypeParameterElementImpl element =
+ new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+ element.bound =
+ (classS.type as TypeImpl).withNullability(NullabilitySuffix.star);
+ TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+ .withNullability(NullabilitySuffix.question);
+ expect(
+ type.resolveToBound(null),
+ equals((classS.type as TypeImpl)
+ .withNullability(NullabilitySuffix.question)));
+ }
+
+ void test_resolveToBound_bound_nullableOuter() {
+ ClassElementImpl classS = ElementFactory.classElement2("A");
+ TypeParameterElementImpl element =
+ new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+ element.bound = classS.type;
+ TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+ .withNullability(NullabilitySuffix.question);
+ expect(
+ type.resolveToBound(null),
+ equals((classS.type as TypeImpl)
+ .withNullability(NullabilitySuffix.question)));
+ }
+
+ void test_resolveToBound_bound_starInner() {
+ ClassElementImpl classS = ElementFactory.classElement2("A");
+ TypeParameterElementImpl element =
+ new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+ element.bound =
+ (classS.type as TypeImpl).withNullability(NullabilitySuffix.star);
+ TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
+ expect(type.resolveToBound(null), same(element.bound));
+ }
+
+ void test_resolveToBound_bound_starInnerNullableOuter() {
+ ClassElementImpl classS = ElementFactory.classElement2("A");
+ TypeParameterElementImpl element =
+ new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+ element.bound =
+ (classS.type as TypeImpl).withNullability(NullabilitySuffix.question);
+ TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+ .withNullability(NullabilitySuffix.star);
+ expect(type.resolveToBound(null), same(element.bound));
+ }
+
+ void test_resolveToBound_bound_starOuter() {
+ ClassElementImpl classS = ElementFactory.classElement2("A");
+ TypeParameterElementImpl element =
+ new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+ element.bound = classS.type;
+ TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+ .withNullability(NullabilitySuffix.star);
+ expect(
+ type.resolveToBound(null),
+ same(
+ (classS.type as TypeImpl).withNullability(NullabilitySuffix.star)));
+ }
+
void test_resolveToBound_nestedBound() {
ClassElementImpl classS = ElementFactory.classElement2("A");
TypeParameterElementImpl elementE =
diff --git a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
index 0011f32..8a57412 100644
--- a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
@@ -26,6 +26,18 @@
@override
bool get typeToStringWithNullability => true;
+ test_member_potentiallyNullable_called() async {
+ addTestFile(r'''
+m<T extends Function>() {
+ List<T?> x;
+ x.first();
+}
+''');
+ await resolveTestFile();
+ // Do not assert no test errors. Deliberately invokes nullable type.
+ assertType(findNode.methodInvocation('first').methodName, 'Function?');
+ }
+
test_local_getterNullAwareAccess_interfaceType() async {
addTestFile(r'''
m() {