[dartdevc] Allow mutual subtypes in type argument bounds

Back-porting a breaking change for Null Safety to the existing SDK to
help front load any issues (we expect them to be minimal).
https://github.com/dart-lang/sdk/issues/40633

We are now allowing the type argument bounds in generic function
subtypes to differ if the bounds are mutual subtypes.

Change-Id: I2b093c08f772a1b866dbe1324b605e6143d3a0b4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/137289
Reviewed-by: Mark Zhou <markzipan@google.com>
Commit-Queue: Nicholas Shahan <nshahan@google.com>
This commit is contained in:
Nicholas Shahan 2020-02-27 23:35:53 +00:00 committed by commit-bot@chromium.org
parent 63e36183ae
commit 15b6f19008
2 changed files with 11 additions and 16 deletions

View file

@ -962,19 +962,20 @@ bool _isSubtype(t1, t2) => JS('', '''(() => {
// Without type bounds all will instantiate to dynamic. Only need to check
// further if at least one of the functions has type bounds.
if ($t1.hasTypeBounds || $t2.hasTypeBounds) {
// Check the bounds of the type parameters of g1 and g2.
// given a type parameter `T1 extends U1` from g1, and a type parameter
// `T2 extends U2` from g2, we must ensure that:
//
// U2 == U1
// Check the bounds of the type parameters of g1 and g2. Given a type
// parameter `T1 extends U1` from g1, and a type parameter `T2 extends U2`
// from g2, we must ensure that U1 and U2 are mutual subtypes.
//
// (Note there is no variance in the type bounds of type parameters of
// generic functions).
let t1Bounds = $t1.instantiateTypeBounds(fresh);
let t2Bounds = $t2.instantiateTypeBounds(fresh);
for (let i = 0; i < formalCount; i++) {
if (t2Bounds[i] != t1Bounds[i]) {
return false;
if (t1Bounds[i] != t2Bounds[i]) {
if (!($_isSubtype(t1Bounds[i], t2Bounds[i])
&& $_isSubtype(t2Bounds[i], t1Bounds[i]))) {
return false;
}
}
}
}

View file

@ -1414,15 +1414,9 @@ bool _isSubtype(t1, t2, bool strictMode) => JS('bool', '''(() => {
// Without type bounds all will instantiate to dynamic. Only need to check
// further if at least one of the functions has type bounds.
if ($t1.hasTypeBounds || $t2.hasTypeBounds) {
// Check the bounds of the type parameters of g1 and g2.
// given a type parameter `T1 extends U1` from g1, and a type parameter
// `T2 extends U2` from g2, we must ensure that:
//
// U1 == U2
//
// given a legacy type can be equivalent to nullable or non-nullable
// versions of the same type. The language spec recomends testing for
// mutual subtypes to allow this behaivor.
// Check the bounds of the type parameters of g1 and g2. Given a type
// parameter `T1 extends U1` from g1, and a type parameter `T2 extends U2`
// from g2, we must ensure that U1 and U2 are mutual subtypes.
//
// (Note there is no variance in the type bounds of type parameters of
// generic functions).