Update UP for FutureOr.

Bug: https://github.com/dart-lang/sdk/issues/43720
Change-Id: I9decd3a3b430f82e3e4bd0c4e6963cd3069f9adf
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166786
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2020-10-09 00:00:55 +00:00 committed by commit-bot@chromium.org
parent 63e0cd6955
commit 694c8d0d6b
2 changed files with 99 additions and 0 deletions

View file

@ -677,6 +677,11 @@ class LeastUpperBoundHelper {
return getLeastUpperBound(T1, _typeSystem.objectNone);
}
var futureOrResult = _futureOr(T1, T2);
if (futureOrResult != null) {
return futureOrResult;
}
// UP(T1, T2) = T2 if T1 <: T2
// UP(T1, T2) = T1 if T2 <: T1
// And other, more complex variants of interface types.
@ -806,6 +811,56 @@ class LeastUpperBoundHelper {
);
}
DartType _futureOr(DartType T1, DartType T2) {
var T1_futureOr = T1 is InterfaceType && T1.isDartAsyncFutureOr
? T1.typeArguments[0]
: null;
var T1_future = T1 is InterfaceType && T1.isDartAsyncFuture
? T1.typeArguments[0]
: null;
var T2_futureOr = T2 is InterfaceType && T2.isDartAsyncFutureOr
? T2.typeArguments[0]
: null;
var T2_future = T2 is InterfaceType && T2.isDartAsyncFuture
? T2.typeArguments[0]
: null;
// UP(FutureOr<T1>, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
if (T1_futureOr != null && T2_futureOr != null) {
var T3 = getLeastUpperBound(T1_futureOr, T2_futureOr);
return _typeSystem.typeProvider.futureOrType2(T3);
}
// UP(Future<T1>, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
if (T1_future != null && T2_futureOr != null) {
var T3 = getLeastUpperBound(T1_future, T2_futureOr);
return _typeSystem.typeProvider.futureOrType2(T3);
}
// UP(FutureOr<T1>, Future<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
if (T1_futureOr != null && T2_future != null) {
var T3 = getLeastUpperBound(T1_futureOr, T2_future);
return _typeSystem.typeProvider.futureOrType2(T3);
}
// UP(T1, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
if (T2_futureOr != null) {
var T3 = getLeastUpperBound(T1, T2_futureOr);
return _typeSystem.typeProvider.futureOrType2(T3);
}
// UP(FutureOr<T1>, T2) = FutureOr<T3> where T3 = UP(T1, T2)
if (T1_futureOr != null) {
var T3 = getLeastUpperBound(T1_futureOr, T2);
return _typeSystem.typeProvider.futureOrType2(T3);
}
return null;
}
DartType _parameterType(ParameterElement a, ParameterElement b) {
return _typeSystem.getGreatestLowerBound(a.type, b.type);
}

View file

@ -2608,6 +2608,50 @@ class UpperBoundTest extends _BoundsTestBase {
);
}
/// UP(Future<T1>, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
/// UP(FutureOr<T1>, Future<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
test_futureOr_future() {
void check(DartType T1, DartType T2, DartType expected) {
_checkLeastUpperBound(
futureNone(T1),
futureOrNone(T2),
futureOrNone(expected),
);
}
check(intNone, doubleNone, numNone);
check(intNone, stringNone, objectNone);
}
/// UP(FutureOr<T1>, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
test_futureOr_futureOr() {
void check(DartType T1, DartType T2, DartType expected) {
_checkLeastUpperBound(
futureOrNone(T1),
futureOrNone(T2),
futureOrNone(expected),
);
}
check(intNone, doubleNone, numNone);
check(intNone, stringNone, objectNone);
}
/// UP(T1, FutureOr<T2>) = FutureOr<T3> where T3 = UP(T1, T2)
/// UP(FutureOr<T1>, T2) = FutureOr<T3> where T3 = UP(T1, T2)
test_futureOr_other() {
void check(DartType T1, DartType T2, DartType expected) {
_checkLeastUpperBound(
futureOrNone(T1),
T2,
futureOrNone(expected),
);
}
check(intNone, doubleNone, numNone);
check(intNone, stringNone, objectNone);
}
test_identical() {
void check(DartType type) {
_checkLeastUpperBound(type, type, type);