Skip to content

Commit

Permalink
[dartdevc] Allow mutual subtypes in type argument bounds
Browse files Browse the repository at this point in the history
Back-porting a breaking change for Null Safety to the existing SDK to
help front load any issues (we expect them to be minimal).
#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>
  • Loading branch information
nshahan authored and commit-bot@chromium.org committed Feb 27, 2020
1 parent 63e3618 commit 15b6f19
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 16 deletions.
15 changes: 8 additions & 7 deletions sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down

0 comments on commit 15b6f19

Please sign in to comment.