Version 2.15.0-210.0.dev
Merge commit 'd83e78c7a37e86b8b70b34cee0777e9b516e314f' into 'dev'
diff --git a/DEPS b/DEPS
index 00f0e0c..c6cd91f 100644
--- a/DEPS
+++ b/DEPS
@@ -85,7 +85,7 @@
"characters_rev": "6ec389c4dfa8fce14820dc5cbf6e693202e7e052",
"charcode_rev": "84ea427711e24abf3b832923959caa7dd9a8514b",
"chrome_rev" : "19997",
- "cli_util_rev" : "71ba36e2554f7b7717f3f12b5ddd33751a4e3ddd",
+ "cli_util_rev" : "b0adbba89442b2ea6fef39c7a82fe79cb31e1168",
"clock_rev" : "a494269254ba978e7ef8f192c5f7fec3fc05b9d3",
"collection_rev": "a4c941ab94044d118b2086a3f261c30377604127",
"convert_rev": "e063fdca4bebffecbb5e6aa5525995120982d9ce",
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index e1dfd44..426a2e0 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -10,7 +10,12 @@
import 'package:kernel/src/bounds_checks.dart';
import 'package:kernel/src/legacy_erasure.dart';
import 'package:kernel/src/types.dart' show Types;
-import 'package:kernel/type_algebra.dart' show Substitution;
+import 'package:kernel/type_algebra.dart'
+ show
+ FreshTypeParameters,
+ Substitution,
+ getFreshTypeParameters,
+ updateBoundNullabilities;
import 'package:kernel/type_environment.dart';
import '../builder/builder.dart';
@@ -1287,16 +1292,34 @@
} else if (declaredFunction?.typeParameters != null) {
Map<TypeParameter, DartType> substitutionMap =
<TypeParameter, DartType>{};
+
+ // Since the bound of `interfaceFunction!.parameter[i]` may have changed
+ // during substitution, it can affect the nullabilities of the types in
+ // the substitution map. The first parameter to
+ // [TypeParameterType.forAlphaRenaming] should be updated to account for
+ // the change.
+ List<TypeParameter> interfaceTypeParameters;
+ if (interfaceSubstitution == null) {
+ interfaceTypeParameters = interfaceFunction!.typeParameters;
+ } else {
+ FreshTypeParameters freshTypeParameters =
+ getFreshTypeParameters(interfaceFunction!.typeParameters);
+ interfaceTypeParameters = freshTypeParameters.freshTypeParameters;
+ for (TypeParameter parameter in interfaceTypeParameters) {
+ parameter.bound =
+ interfaceSubstitution.substituteType(parameter.bound);
+ }
+ updateBoundNullabilities(interfaceTypeParameters);
+ }
for (int i = 0; i < declaredFunction!.typeParameters.length; ++i) {
- substitutionMap[interfaceFunction!.typeParameters[i]] =
+ substitutionMap[interfaceFunction.typeParameters[i]] =
new TypeParameterType.forAlphaRenaming(
- interfaceFunction.typeParameters[i],
- declaredFunction.typeParameters[i]);
+ interfaceTypeParameters[i], declaredFunction.typeParameters[i]);
}
Substitution substitution = Substitution.fromMap(substitutionMap);
for (int i = 0; i < declaredFunction.typeParameters.length; ++i) {
TypeParameter declaredParameter = declaredFunction.typeParameters[i];
- TypeParameter interfaceParameter = interfaceFunction!.typeParameters[i];
+ TypeParameter interfaceParameter = interfaceFunction.typeParameters[i];
if (!interfaceParameter.isCovariantByClass) {
DartType declaredBound = declaredParameter.bound;
DartType interfaceBound = interfaceParameter.bound;
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 93046af..cad9efd 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -2415,6 +2415,7 @@
reasons
reassign
rebase
+recalculates
receive
receiver
recent
diff --git a/pkg/front_end/testcases/nnbd/issue47311.dart b/pkg/front_end/testcases/nnbd/issue47311.dart
new file mode 100644
index 0000000..7fef532
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue47311.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+typedef Baz<T> = T Function(T);
+
+class Foo1<T> {
+ void method<S extends T>(Baz<S> x) {}
+}
+
+class Bar1 implements Foo1<Object> {
+ void method<T extends Object>(Baz<T> x) {}
+}
+
+class Foo2<T> {
+ void method<V extends S, S extends T>(Baz<S> x, Baz<V> y) {}
+}
+
+class Bar2 implements Foo2<Object> {
+ void method<V extends T, T extends Object>(Baz<T> x, Baz<V> y) {}
+}
+
+class Foo3<T> {
+ void method<V extends S, S extends FutureOr<T>>(Baz<S> x, Baz<V> y) {}
+}
+
+class Bar3 implements Foo3<Object> {
+ void method<V extends T, T extends FutureOr<Object>>(Baz<T> x, Baz<V> y) {}
+}
+
+class Foo4<T> {
+ void method<V extends FutureOr<S>, S extends T>(Baz<S> x, Baz<V> y) {}
+}
+
+class Bar4 implements Foo4<Object> {
+ void method<V extends FutureOr<T>, T extends Object>(Baz<T> x, Baz<V> y) {}
+}
+
+class Foo5<T> {
+ void method<V extends FutureOr<S>, S extends FutureOr<T>>(Baz<S> x, Baz<V> y) {}
+}
+
+class Bar5 implements Foo5<Object> {
+ void method<V extends FutureOr<T>, T extends FutureOr<Object>>(Baz<T> x, Baz<V> y) {}
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue47311.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue47311.dart.strong.expect
new file mode 100644
index 0000000..baea864
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue47311.dart.strong.expect
@@ -0,0 +1,68 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef Baz<invariant T extends core::Object? = dynamic> = (T%) → T%;
+class Foo1<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo1<self::Foo1::T%>
+ : super core::Object::•()
+ ;
+ method method<covariant-by-class S extends self::Foo1::T%>((self::Foo1::method::S%) → self::Foo1::method::S% x) → void {}
+}
+class Bar1 extends core::Object implements self::Foo1<core::Object> {
+ synthetic constructor •() → self::Bar1
+ : super core::Object::•()
+ ;
+ method method<covariant-by-class T extends core::Object>((self::Bar1::method::T) → self::Bar1::method::T x) → void {}
+}
+class Foo2<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo2<self::Foo2::T%>
+ : super core::Object::•()
+ ;
+ method method<V extends self::Foo2::method::S% = self::Foo2::T%, covariant-by-class S extends self::Foo2::T%>((self::Foo2::method::S%) → self::Foo2::method::S% x, (self::Foo2::method::V%) → self::Foo2::method::V% y) → void {}
+}
+class Bar2 extends core::Object implements self::Foo2<core::Object> {
+ synthetic constructor •() → self::Bar2
+ : super core::Object::•()
+ ;
+ method method<V extends self::Bar2::method::T = core::Object, covariant-by-class T extends core::Object>((self::Bar2::method::T) → self::Bar2::method::T x, (self::Bar2::method::V) → self::Bar2::method::V y) → void {}
+}
+class Foo3<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo3<self::Foo3::T%>
+ : super core::Object::•()
+ ;
+ method method<V extends self::Foo3::method::S% = FutureOr<self::Foo3::T%>, covariant-by-class S extends FutureOr<self::Foo3::T%>>((self::Foo3::method::S%) → self::Foo3::method::S% x, (self::Foo3::method::V%) → self::Foo3::method::V% y) → void {}
+}
+class Bar3 extends core::Object implements self::Foo3<core::Object> {
+ synthetic constructor •() → self::Bar3
+ : super core::Object::•()
+ ;
+ method method<V extends self::Bar3::method::T = FutureOr<core::Object>, covariant-by-class T extends FutureOr<core::Object>>((self::Bar3::method::T) → self::Bar3::method::T x, (self::Bar3::method::V) → self::Bar3::method::V y) → void {}
+}
+class Foo4<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo4<self::Foo4::T%>
+ : super core::Object::•()
+ ;
+ method method<V extends FutureOr<self::Foo4::method::S%> = FutureOr<self::Foo4::T%>, covariant-by-class S extends self::Foo4::T%>((self::Foo4::method::S%) → self::Foo4::method::S% x, (self::Foo4::method::V%) → self::Foo4::method::V% y) → void {}
+}
+class Bar4 extends core::Object implements self::Foo4<core::Object> {
+ synthetic constructor •() → self::Bar4
+ : super core::Object::•()
+ ;
+ method method<V extends FutureOr<self::Bar4::method::T> = FutureOr<core::Object>, covariant-by-class T extends core::Object>((self::Bar4::method::T) → self::Bar4::method::T x, (self::Bar4::method::V) → self::Bar4::method::V y) → void {}
+}
+class Foo5<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo5<self::Foo5::T%>
+ : super core::Object::•()
+ ;
+ method method<V extends FutureOr<self::Foo5::method::S%> = FutureOr<FutureOr<self::Foo5::T%>>, covariant-by-class S extends FutureOr<self::Foo5::T%>>((self::Foo5::method::S%) → self::Foo5::method::S% x, (self::Foo5::method::V%) → self::Foo5::method::V% y) → void {}
+}
+class Bar5 extends core::Object implements self::Foo5<core::Object> {
+ synthetic constructor •() → self::Bar5
+ : super core::Object::•()
+ ;
+ method method<V extends FutureOr<self::Bar5::method::T> = FutureOr<FutureOr<core::Object>>, covariant-by-class T extends FutureOr<core::Object>>((self::Bar5::method::T) → self::Bar5::method::T x, (self::Bar5::method::V) → self::Bar5::method::V y) → void {}
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/nnbd/issue47311.dart.strong.transformed.expect b/pkg/front_end/testcases/nnbd/issue47311.dart.strong.transformed.expect
new file mode 100644
index 0000000..baea864
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue47311.dart.strong.transformed.expect
@@ -0,0 +1,68 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef Baz<invariant T extends core::Object? = dynamic> = (T%) → T%;
+class Foo1<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo1<self::Foo1::T%>
+ : super core::Object::•()
+ ;
+ method method<covariant-by-class S extends self::Foo1::T%>((self::Foo1::method::S%) → self::Foo1::method::S% x) → void {}
+}
+class Bar1 extends core::Object implements self::Foo1<core::Object> {
+ synthetic constructor •() → self::Bar1
+ : super core::Object::•()
+ ;
+ method method<covariant-by-class T extends core::Object>((self::Bar1::method::T) → self::Bar1::method::T x) → void {}
+}
+class Foo2<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo2<self::Foo2::T%>
+ : super core::Object::•()
+ ;
+ method method<V extends self::Foo2::method::S% = self::Foo2::T%, covariant-by-class S extends self::Foo2::T%>((self::Foo2::method::S%) → self::Foo2::method::S% x, (self::Foo2::method::V%) → self::Foo2::method::V% y) → void {}
+}
+class Bar2 extends core::Object implements self::Foo2<core::Object> {
+ synthetic constructor •() → self::Bar2
+ : super core::Object::•()
+ ;
+ method method<V extends self::Bar2::method::T = core::Object, covariant-by-class T extends core::Object>((self::Bar2::method::T) → self::Bar2::method::T x, (self::Bar2::method::V) → self::Bar2::method::V y) → void {}
+}
+class Foo3<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo3<self::Foo3::T%>
+ : super core::Object::•()
+ ;
+ method method<V extends self::Foo3::method::S% = FutureOr<self::Foo3::T%>, covariant-by-class S extends FutureOr<self::Foo3::T%>>((self::Foo3::method::S%) → self::Foo3::method::S% x, (self::Foo3::method::V%) → self::Foo3::method::V% y) → void {}
+}
+class Bar3 extends core::Object implements self::Foo3<core::Object> {
+ synthetic constructor •() → self::Bar3
+ : super core::Object::•()
+ ;
+ method method<V extends self::Bar3::method::T = FutureOr<core::Object>, covariant-by-class T extends FutureOr<core::Object>>((self::Bar3::method::T) → self::Bar3::method::T x, (self::Bar3::method::V) → self::Bar3::method::V y) → void {}
+}
+class Foo4<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo4<self::Foo4::T%>
+ : super core::Object::•()
+ ;
+ method method<V extends FutureOr<self::Foo4::method::S%> = FutureOr<self::Foo4::T%>, covariant-by-class S extends self::Foo4::T%>((self::Foo4::method::S%) → self::Foo4::method::S% x, (self::Foo4::method::V%) → self::Foo4::method::V% y) → void {}
+}
+class Bar4 extends core::Object implements self::Foo4<core::Object> {
+ synthetic constructor •() → self::Bar4
+ : super core::Object::•()
+ ;
+ method method<V extends FutureOr<self::Bar4::method::T> = FutureOr<core::Object>, covariant-by-class T extends core::Object>((self::Bar4::method::T) → self::Bar4::method::T x, (self::Bar4::method::V) → self::Bar4::method::V y) → void {}
+}
+class Foo5<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo5<self::Foo5::T%>
+ : super core::Object::•()
+ ;
+ method method<V extends FutureOr<self::Foo5::method::S%> = FutureOr<FutureOr<self::Foo5::T%>>, covariant-by-class S extends FutureOr<self::Foo5::T%>>((self::Foo5::method::S%) → self::Foo5::method::S% x, (self::Foo5::method::V%) → self::Foo5::method::V% y) → void {}
+}
+class Bar5 extends core::Object implements self::Foo5<core::Object> {
+ synthetic constructor •() → self::Bar5
+ : super core::Object::•()
+ ;
+ method method<V extends FutureOr<self::Bar5::method::T> = FutureOr<FutureOr<core::Object>>, covariant-by-class T extends FutureOr<core::Object>>((self::Bar5::method::T) → self::Bar5::method::T x, (self::Bar5::method::V) → self::Bar5::method::V y) → void {}
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/nnbd/issue47311.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd/issue47311.dart.textual_outline.expect
new file mode 100644
index 0000000..07a20ea
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue47311.dart.textual_outline.expect
@@ -0,0 +1,47 @@
+import 'dart:async';
+
+typedef Baz<T> = T Function(T);
+
+class Foo1<T> {
+ void method<S extends T>(Baz<S> x) {}
+}
+
+class Bar1 implements Foo1<Object> {
+ void method<T extends Object>(Baz<T> x) {}
+}
+
+class Foo2<T> {
+ void method<V extends S, S extends T>(Baz<S> x, Baz<V> y) {}
+}
+
+class Bar2 implements Foo2<Object> {
+ void method<V extends T, T extends Object>(Baz<T> x, Baz<V> y) {}
+}
+
+class Foo3<T> {
+ void method<V extends S, S extends FutureOr<T>>(Baz<S> x, Baz<V> y) {}
+}
+
+class Bar3 implements Foo3<Object> {
+ void method<V extends T, T extends FutureOr<Object>>(Baz<T> x, Baz<V> y) {}
+}
+
+class Foo4<T> {
+ void method<V extends FutureOr<S>, S extends T>(Baz<S> x, Baz<V> y) {}
+}
+
+class Bar4 implements Foo4<Object> {
+ void method<V extends FutureOr<T>, T extends Object>(Baz<T> x, Baz<V> y) {}
+}
+
+class Foo5<T> {
+ void method<V extends FutureOr<S>, S extends FutureOr<T>>(
+ Baz<S> x, Baz<V> y) {}
+}
+
+class Bar5 implements Foo5<Object> {
+ void method<V extends FutureOr<T>, T extends FutureOr<Object>>(
+ Baz<T> x, Baz<V> y) {}
+}
+
+void main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue47311.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd/issue47311.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..fbbf978
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue47311.dart.textual_outline_modelled.expect
@@ -0,0 +1,46 @@
+import 'dart:async';
+
+class Bar1 implements Foo1<Object> {
+ void method<T extends Object>(Baz<T> x) {}
+}
+
+class Bar2 implements Foo2<Object> {
+ void method<V extends T, T extends Object>(Baz<T> x, Baz<V> y) {}
+}
+
+class Bar3 implements Foo3<Object> {
+ void method<V extends T, T extends FutureOr<Object>>(Baz<T> x, Baz<V> y) {}
+}
+
+class Bar4 implements Foo4<Object> {
+ void method<V extends FutureOr<T>, T extends Object>(Baz<T> x, Baz<V> y) {}
+}
+
+class Bar5 implements Foo5<Object> {
+ void method<V extends FutureOr<T>, T extends FutureOr<Object>>(
+ Baz<T> x, Baz<V> y) {}
+}
+
+class Foo1<T> {
+ void method<S extends T>(Baz<S> x) {}
+}
+
+class Foo2<T> {
+ void method<V extends S, S extends T>(Baz<S> x, Baz<V> y) {}
+}
+
+class Foo3<T> {
+ void method<V extends S, S extends FutureOr<T>>(Baz<S> x, Baz<V> y) {}
+}
+
+class Foo4<T> {
+ void method<V extends FutureOr<S>, S extends T>(Baz<S> x, Baz<V> y) {}
+}
+
+class Foo5<T> {
+ void method<V extends FutureOr<S>, S extends FutureOr<T>>(
+ Baz<S> x, Baz<V> y) {}
+}
+
+typedef Baz<T> = T Function(T);
+void main() {}
diff --git a/pkg/front_end/testcases/nnbd/issue47311.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue47311.dart.weak.expect
new file mode 100644
index 0000000..baea864
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue47311.dart.weak.expect
@@ -0,0 +1,68 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef Baz<invariant T extends core::Object? = dynamic> = (T%) → T%;
+class Foo1<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo1<self::Foo1::T%>
+ : super core::Object::•()
+ ;
+ method method<covariant-by-class S extends self::Foo1::T%>((self::Foo1::method::S%) → self::Foo1::method::S% x) → void {}
+}
+class Bar1 extends core::Object implements self::Foo1<core::Object> {
+ synthetic constructor •() → self::Bar1
+ : super core::Object::•()
+ ;
+ method method<covariant-by-class T extends core::Object>((self::Bar1::method::T) → self::Bar1::method::T x) → void {}
+}
+class Foo2<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo2<self::Foo2::T%>
+ : super core::Object::•()
+ ;
+ method method<V extends self::Foo2::method::S% = self::Foo2::T%, covariant-by-class S extends self::Foo2::T%>((self::Foo2::method::S%) → self::Foo2::method::S% x, (self::Foo2::method::V%) → self::Foo2::method::V% y) → void {}
+}
+class Bar2 extends core::Object implements self::Foo2<core::Object> {
+ synthetic constructor •() → self::Bar2
+ : super core::Object::•()
+ ;
+ method method<V extends self::Bar2::method::T = core::Object, covariant-by-class T extends core::Object>((self::Bar2::method::T) → self::Bar2::method::T x, (self::Bar2::method::V) → self::Bar2::method::V y) → void {}
+}
+class Foo3<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo3<self::Foo3::T%>
+ : super core::Object::•()
+ ;
+ method method<V extends self::Foo3::method::S% = FutureOr<self::Foo3::T%>, covariant-by-class S extends FutureOr<self::Foo3::T%>>((self::Foo3::method::S%) → self::Foo3::method::S% x, (self::Foo3::method::V%) → self::Foo3::method::V% y) → void {}
+}
+class Bar3 extends core::Object implements self::Foo3<core::Object> {
+ synthetic constructor •() → self::Bar3
+ : super core::Object::•()
+ ;
+ method method<V extends self::Bar3::method::T = FutureOr<core::Object>, covariant-by-class T extends FutureOr<core::Object>>((self::Bar3::method::T) → self::Bar3::method::T x, (self::Bar3::method::V) → self::Bar3::method::V y) → void {}
+}
+class Foo4<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo4<self::Foo4::T%>
+ : super core::Object::•()
+ ;
+ method method<V extends FutureOr<self::Foo4::method::S%> = FutureOr<self::Foo4::T%>, covariant-by-class S extends self::Foo4::T%>((self::Foo4::method::S%) → self::Foo4::method::S% x, (self::Foo4::method::V%) → self::Foo4::method::V% y) → void {}
+}
+class Bar4 extends core::Object implements self::Foo4<core::Object> {
+ synthetic constructor •() → self::Bar4
+ : super core::Object::•()
+ ;
+ method method<V extends FutureOr<self::Bar4::method::T> = FutureOr<core::Object>, covariant-by-class T extends core::Object>((self::Bar4::method::T) → self::Bar4::method::T x, (self::Bar4::method::V) → self::Bar4::method::V y) → void {}
+}
+class Foo5<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo5<self::Foo5::T%>
+ : super core::Object::•()
+ ;
+ method method<V extends FutureOr<self::Foo5::method::S%> = FutureOr<FutureOr<self::Foo5::T%>>, covariant-by-class S extends FutureOr<self::Foo5::T%>>((self::Foo5::method::S%) → self::Foo5::method::S% x, (self::Foo5::method::V%) → self::Foo5::method::V% y) → void {}
+}
+class Bar5 extends core::Object implements self::Foo5<core::Object> {
+ synthetic constructor •() → self::Bar5
+ : super core::Object::•()
+ ;
+ method method<V extends FutureOr<self::Bar5::method::T> = FutureOr<FutureOr<core::Object>>, covariant-by-class T extends FutureOr<core::Object>>((self::Bar5::method::T) → self::Bar5::method::T x, (self::Bar5::method::V) → self::Bar5::method::V y) → void {}
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/nnbd/issue47311.dart.weak.outline.expect b/pkg/front_end/testcases/nnbd/issue47311.dart.weak.outline.expect
new file mode 100644
index 0000000..7bf55ff
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue47311.dart.weak.outline.expect
@@ -0,0 +1,69 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef Baz<invariant T extends core::Object? = dynamic> = (T%) → T%;
+class Foo1<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo1<self::Foo1::T%>
+ ;
+ method method<covariant-by-class S extends self::Foo1::T%>((self::Foo1::method::S%) → self::Foo1::method::S% x) → void
+ ;
+}
+class Bar1 extends core::Object implements self::Foo1<core::Object> {
+ synthetic constructor •() → self::Bar1
+ ;
+ method method<covariant-by-class T extends core::Object>((self::Bar1::method::T) → self::Bar1::method::T x) → void
+ ;
+}
+class Foo2<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo2<self::Foo2::T%>
+ ;
+ method method<V extends self::Foo2::method::S% = self::Foo2::T%, covariant-by-class S extends self::Foo2::T%>((self::Foo2::method::S%) → self::Foo2::method::S% x, (self::Foo2::method::V%) → self::Foo2::method::V% y) → void
+ ;
+}
+class Bar2 extends core::Object implements self::Foo2<core::Object> {
+ synthetic constructor •() → self::Bar2
+ ;
+ method method<V extends self::Bar2::method::T = core::Object, covariant-by-class T extends core::Object>((self::Bar2::method::T) → self::Bar2::method::T x, (self::Bar2::method::V) → self::Bar2::method::V y) → void
+ ;
+}
+class Foo3<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo3<self::Foo3::T%>
+ ;
+ method method<V extends self::Foo3::method::S% = FutureOr<self::Foo3::T%>, covariant-by-class S extends FutureOr<self::Foo3::T%>>((self::Foo3::method::S%) → self::Foo3::method::S% x, (self::Foo3::method::V%) → self::Foo3::method::V% y) → void
+ ;
+}
+class Bar3 extends core::Object implements self::Foo3<core::Object> {
+ synthetic constructor •() → self::Bar3
+ ;
+ method method<V extends self::Bar3::method::T = FutureOr<core::Object>, covariant-by-class T extends FutureOr<core::Object>>((self::Bar3::method::T) → self::Bar3::method::T x, (self::Bar3::method::V) → self::Bar3::method::V y) → void
+ ;
+}
+class Foo4<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo4<self::Foo4::T%>
+ ;
+ method method<V extends FutureOr<self::Foo4::method::S%> = FutureOr<self::Foo4::T%>, covariant-by-class S extends self::Foo4::T%>((self::Foo4::method::S%) → self::Foo4::method::S% x, (self::Foo4::method::V%) → self::Foo4::method::V% y) → void
+ ;
+}
+class Bar4 extends core::Object implements self::Foo4<core::Object> {
+ synthetic constructor •() → self::Bar4
+ ;
+ method method<V extends FutureOr<self::Bar4::method::T> = FutureOr<core::Object>, covariant-by-class T extends core::Object>((self::Bar4::method::T) → self::Bar4::method::T x, (self::Bar4::method::V) → self::Bar4::method::V y) → void
+ ;
+}
+class Foo5<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo5<self::Foo5::T%>
+ ;
+ method method<V extends FutureOr<self::Foo5::method::S%> = FutureOr<FutureOr<self::Foo5::T%>>, covariant-by-class S extends FutureOr<self::Foo5::T%>>((self::Foo5::method::S%) → self::Foo5::method::S% x, (self::Foo5::method::V%) → self::Foo5::method::V% y) → void
+ ;
+}
+class Bar5 extends core::Object implements self::Foo5<core::Object> {
+ synthetic constructor •() → self::Bar5
+ ;
+ method method<V extends FutureOr<self::Bar5::method::T> = FutureOr<FutureOr<core::Object>>, covariant-by-class T extends FutureOr<core::Object>>((self::Bar5::method::T) → self::Bar5::method::T x, (self::Bar5::method::V) → self::Bar5::method::V y) → void
+ ;
+}
+static method main() → void
+ ;
diff --git a/pkg/front_end/testcases/nnbd/issue47311.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd/issue47311.dart.weak.transformed.expect
new file mode 100644
index 0000000..baea864
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd/issue47311.dart.weak.transformed.expect
@@ -0,0 +1,68 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+import "dart:async";
+
+typedef Baz<invariant T extends core::Object? = dynamic> = (T%) → T%;
+class Foo1<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo1<self::Foo1::T%>
+ : super core::Object::•()
+ ;
+ method method<covariant-by-class S extends self::Foo1::T%>((self::Foo1::method::S%) → self::Foo1::method::S% x) → void {}
+}
+class Bar1 extends core::Object implements self::Foo1<core::Object> {
+ synthetic constructor •() → self::Bar1
+ : super core::Object::•()
+ ;
+ method method<covariant-by-class T extends core::Object>((self::Bar1::method::T) → self::Bar1::method::T x) → void {}
+}
+class Foo2<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo2<self::Foo2::T%>
+ : super core::Object::•()
+ ;
+ method method<V extends self::Foo2::method::S% = self::Foo2::T%, covariant-by-class S extends self::Foo2::T%>((self::Foo2::method::S%) → self::Foo2::method::S% x, (self::Foo2::method::V%) → self::Foo2::method::V% y) → void {}
+}
+class Bar2 extends core::Object implements self::Foo2<core::Object> {
+ synthetic constructor •() → self::Bar2
+ : super core::Object::•()
+ ;
+ method method<V extends self::Bar2::method::T = core::Object, covariant-by-class T extends core::Object>((self::Bar2::method::T) → self::Bar2::method::T x, (self::Bar2::method::V) → self::Bar2::method::V y) → void {}
+}
+class Foo3<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo3<self::Foo3::T%>
+ : super core::Object::•()
+ ;
+ method method<V extends self::Foo3::method::S% = FutureOr<self::Foo3::T%>, covariant-by-class S extends FutureOr<self::Foo3::T%>>((self::Foo3::method::S%) → self::Foo3::method::S% x, (self::Foo3::method::V%) → self::Foo3::method::V% y) → void {}
+}
+class Bar3 extends core::Object implements self::Foo3<core::Object> {
+ synthetic constructor •() → self::Bar3
+ : super core::Object::•()
+ ;
+ method method<V extends self::Bar3::method::T = FutureOr<core::Object>, covariant-by-class T extends FutureOr<core::Object>>((self::Bar3::method::T) → self::Bar3::method::T x, (self::Bar3::method::V) → self::Bar3::method::V y) → void {}
+}
+class Foo4<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo4<self::Foo4::T%>
+ : super core::Object::•()
+ ;
+ method method<V extends FutureOr<self::Foo4::method::S%> = FutureOr<self::Foo4::T%>, covariant-by-class S extends self::Foo4::T%>((self::Foo4::method::S%) → self::Foo4::method::S% x, (self::Foo4::method::V%) → self::Foo4::method::V% y) → void {}
+}
+class Bar4 extends core::Object implements self::Foo4<core::Object> {
+ synthetic constructor •() → self::Bar4
+ : super core::Object::•()
+ ;
+ method method<V extends FutureOr<self::Bar4::method::T> = FutureOr<core::Object>, covariant-by-class T extends core::Object>((self::Bar4::method::T) → self::Bar4::method::T x, (self::Bar4::method::V) → self::Bar4::method::V y) → void {}
+}
+class Foo5<T extends core::Object? = dynamic> extends core::Object {
+ synthetic constructor •() → self::Foo5<self::Foo5::T%>
+ : super core::Object::•()
+ ;
+ method method<V extends FutureOr<self::Foo5::method::S%> = FutureOr<FutureOr<self::Foo5::T%>>, covariant-by-class S extends FutureOr<self::Foo5::T%>>((self::Foo5::method::S%) → self::Foo5::method::S% x, (self::Foo5::method::V%) → self::Foo5::method::V% y) → void {}
+}
+class Bar5 extends core::Object implements self::Foo5<core::Object> {
+ synthetic constructor •() → self::Bar5
+ : super core::Object::•()
+ ;
+ method method<V extends FutureOr<self::Bar5::method::T> = FutureOr<FutureOr<core::Object>>, covariant-by-class T extends FutureOr<core::Object>>((self::Bar5::method::T) → self::Bar5::method::T x, (self::Bar5::method::V) → self::Bar5::method::V y) → void {}
+}
+static method main() → void {}
diff --git a/pkg/kernel/lib/type_algebra.dart b/pkg/kernel/lib/type_algebra.dart
index f836d1e..af4b1d0 100644
--- a/pkg/kernel/lib/type_algebra.dart
+++ b/pkg/kernel/lib/type_algebra.dart
@@ -1422,3 +1422,60 @@
? TypeParameterType.computeNullabilityFromBound(parameter)
: Nullability.legacy;
}
+
+/// Recalculates and updates nullabilities of the bounds in [typeParameters].
+///
+/// The procedure is intended to be used on type parameters that are in the
+/// scope of another declaration with type parameters. After a substitution
+/// involving the outer type parameters is performed, some potentially nullable
+/// bounds of the inner parameters can change to non-nullable. Since type
+/// parameters can depend on each other, the occurrences of those with changed
+/// nullabilities need to be updated in the bounds of the entire type parameter
+/// set.
+void updateBoundNullabilities(List<TypeParameter> typeParameters) {
+ if (typeParameters.isEmpty) return;
+ List<bool> visited =
+ new List<bool>.filled(typeParameters.length, false, growable: false);
+ for (int parameterIndex = 0;
+ parameterIndex < typeParameters.length;
+ parameterIndex++) {
+ _updateBoundNullabilities(typeParameters, visited, parameterIndex);
+ }
+}
+
+void _updateBoundNullabilities(
+ List<TypeParameter> typeParameters, List<bool> visited, int startIndex) {
+ if (visited[startIndex]) return;
+ visited[startIndex] = true;
+
+ TypeParameter parameter = typeParameters[startIndex];
+ DartType bound = parameter.bound;
+ while (bound is FutureOrType) {
+ bound = bound.typeArgument;
+ }
+ if (bound is TypeParameterType) {
+ int nextIndex = typeParameters.indexOf(bound.parameter);
+ if (nextIndex != -1) {
+ _updateBoundNullabilities(typeParameters, visited, nextIndex);
+ Nullability updatedNullability =
+ TypeParameterType.computeNullabilityFromBound(
+ typeParameters[nextIndex]);
+ if (bound.declaredNullability != updatedNullability) {
+ parameter.bound = _updateNestedFutureOrNullability(
+ parameter.bound, updatedNullability);
+ }
+ }
+ }
+}
+
+DartType _updateNestedFutureOrNullability(
+ DartType typeToUpdate, Nullability updatedNullability) {
+ if (typeToUpdate is FutureOrType) {
+ return new FutureOrType(
+ _updateNestedFutureOrNullability(
+ typeToUpdate.typeArgument, updatedNullability),
+ typeToUpdate.declaredNullability);
+ } else {
+ return typeToUpdate.withDeclaredNullability(updatedNullability);
+ }
+}
diff --git a/runtime/tests/vm/dart/rematerialize_unboxed_double_field_test.dart b/runtime/tests/vm/dart/rematerialize_unboxed_double_field_test.dart
index cf764a2..b025120 100644
--- a/runtime/tests/vm/dart/rematerialize_unboxed_double_field_test.dart
+++ b/runtime/tests/vm/dart/rematerialize_unboxed_double_field_test.dart
@@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
-// VMOptions=--deterministic --optimization-counter-threshold=10 --unbox-numeric-fields
+// VMOptions=--deterministic --optimization-counter-threshold=100 --unbox-numeric-fields
import 'package:expect/expect.dart';
@@ -29,9 +29,9 @@
void main(List<String> args) {
var c = C();
- for (var i = 0; i < 100; i++) c.d = 2.0;
+ for (var i = 0; i < 200; i++) c.d = 2.0;
- for (var i = 0; i < 100; i++) {
+ for (var i = 0; i < 200; i++) {
foo(NoopSink());
}
diff --git a/runtime/tests/vm/dart_2/rematerialize_unboxed_double_field_test.dart b/runtime/tests/vm/dart_2/rematerialize_unboxed_double_field_test.dart
index d8e037f..b15d7ff 100644
--- a/runtime/tests/vm/dart_2/rematerialize_unboxed_double_field_test.dart
+++ b/runtime/tests/vm/dart_2/rematerialize_unboxed_double_field_test.dart
@@ -2,7 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
-// VMOptions=--deterministic --optimization-counter-threshold=10 --unbox-numeric-fields
+// VMOptions=--deterministic --optimization-counter-threshold=100 --unbox-numeric-fields
// @dart = 2.9
@@ -31,9 +31,9 @@
void main(List<String> args) {
var c = C();
- for (var i = 0; i < 100; i++) c.d = 2.0;
+ for (var i = 0; i < 200; i++) c.d = 2.0;
- for (var i = 0; i < 100; i++) {
+ for (var i = 0; i < 200; i++) {
foo(NoopSink());
}
diff --git a/tools/VERSION b/tools/VERSION
index 05bc800..2a7370b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 15
PATCH 0
-PRERELEASE 209
+PRERELEASE 210
PRERELEASE_PATCH 0
\ No newline at end of file