Update nullability for TypeParameterType in tryPromoteToType()
Change-Id: Ifc8c32e3540577437c6448fa943d8cbbfebf0b62
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196105
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/type_parameter.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/type_parameter.dart
index c818df6..5b091df 100644
--- a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/type_parameter.dart
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/type_parameter.dart
@@ -12,7 +12,7 @@
void promoteNullable(T? t) {
T? s;
if (t is int) {
- s = /*analyzer.T? & int*/ /*cfe.T & int*/ t;
+ s = /*T & int*/ t;
}
}
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index ca7f2f9..6e82d71 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -1506,7 +1506,10 @@
var declaration = from.element.declaration;
return TypeParameterTypeImpl(
element: declaration,
- nullabilitySuffix: from.nullabilitySuffix,
+ nullabilitySuffix: _promotedTypeParameterTypeNullability(
+ from.nullabilitySuffix,
+ to.nullabilitySuffix,
+ ),
promotedBound: to,
);
}
@@ -1866,6 +1869,35 @@
recurse(type);
return result;
}
+
+ static NullabilitySuffix _promotedTypeParameterTypeNullability(
+ NullabilitySuffix nullabilityOfType,
+ NullabilitySuffix nullabilityOfBound,
+ ) {
+ if (nullabilityOfType == NullabilitySuffix.question &&
+ nullabilityOfBound == NullabilitySuffix.none) {
+ return NullabilitySuffix.none;
+ }
+
+ if (nullabilityOfType == NullabilitySuffix.question &&
+ nullabilityOfBound == NullabilitySuffix.question) {
+ return NullabilitySuffix.question;
+ }
+
+ if (nullabilityOfType == NullabilitySuffix.star &&
+ nullabilityOfBound == NullabilitySuffix.none) {
+ return NullabilitySuffix.star;
+ }
+
+ // Intersection with a non-nullable type always yields a non-nullable type,
+ // as it's the most restrictive kind of types.
+ if (nullabilityOfType == NullabilitySuffix.none ||
+ nullabilityOfBound == NullabilitySuffix.none) {
+ return NullabilitySuffix.none;
+ }
+
+ return NullabilitySuffix.star;
+ }
}
/// TODO(scheglov) Ask the language team how to deal with it.
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index 6a50ac8..492236c 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -4,6 +4,7 @@
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/element/element.dart';
@@ -472,22 +473,51 @@
return typeSystem.tryPromoteToType(to, from) as TypeParameterTypeImpl;
}
- void check(
- TypeParameterTypeImpl type,
- TypeParameterElement expectedElement,
- DartType expectedBound,
- ) {
- expect(type.element, expectedElement);
- expect(type.promotedBound, expectedBound);
+ void check(TypeParameterTypeImpl type, String expected) {
+ expect(type.getDisplayString(withNullability: true), expected);
}
var T = typeParameter('T');
- var T0 = typeParameterTypeNone(T);
+ var T_none = typeParameterTypeNone(T);
+ var T_question = typeParameterTypeQuestion(T);
+ var T_star = typeParameterTypeStar(T);
- var T1 = tryPromote(numNone, T0);
- check(T1, T, numNone);
+ check(tryPromote(numNone, T_none), 'T & num');
+ check(tryPromote(numQuestion, T_none), 'T & num?');
+ check(tryPromote(numStar, T_none), 'T & num*');
+
+ check(tryPromote(numNone, T_question), 'T & num');
+ check(tryPromote(numQuestion, T_question), 'T? & num?');
+ check(tryPromote(numStar, T_question), 'T* & num*');
+
+ check(tryPromote(numNone, T_star), 'T* & num');
+ check(tryPromote(numQuestion, T_star), 'T* & num?');
+ check(tryPromote(numStar, T_star), 'T* & num*');
+ }
+
+ test_typeParameter_twice() {
+ TypeParameterTypeImpl tryPromote(DartType to, TypeParameterTypeImpl from) {
+ return typeSystem.tryPromoteToType(to, from) as TypeParameterTypeImpl;
+ }
+
+ void check(
+ TypeParameterTypeImpl type,
+ TypeParameterElement element,
+ NullabilitySuffix nullability,
+ DartType promotedBound,
+ ) {
+ expect(type.element, element);
+ expect(type.nullabilitySuffix, nullability);
+ expect(type.promotedBound, promotedBound);
+ }
+
+ var T = typeParameter('T');
+ var T_none = typeParameterTypeNone(T);
+
+ var T1 = tryPromote(numNone, T_none);
+ check(T1, T, NullabilitySuffix.none, numNone);
var T2 = tryPromote(intNone, T1);
- check(T2, T, intNone);
+ check(T2, T, NullabilitySuffix.none, intNone);
}
}