Version 2.14.0-79.0.dev
Merge commit 'bde30978601e0167a5b9261f259c3b4916146881' into 'dev'
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index b687d8c..996f87c 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -877,10 +877,18 @@
}
return _emitInterfaceType(t, emitNullability: emitNullability);
} else if (t is FutureOrType) {
- _declareBeforeUse(_coreTypes.deprecatedFutureOrClass);
- // TODO(45870) Add nullability wrappers to FutureOr.
- return _emitFutureOrTypeWithArgument(
- _emitDeferredType(t.typeArgument));
+ var normalizedType = _normalizeFutureOr(t);
+ if (normalizedType is FutureOrType) {
+ _declareBeforeUse(_coreTypes.deprecatedFutureOrClass);
+ var typeRep = _emitFutureOrTypeWithArgument(
+ _emitDeferredType(normalizedType.typeArgument));
+ return emitNullability
+ ? _emitNullabilityWrapper(
+ typeRep, normalizedType.declaredNullability)
+ : typeRep;
+ }
+ return _emitDeferredType(normalizedType,
+ emitNullability: emitNullability);
} else if (t is TypeParameterType) {
return _emitTypeParameterType(t, emitNullability: emitNullability);
}
@@ -2720,16 +2728,19 @@
? visitNullType(const NullType())
: _emitNullabilityWrapper(runtimeCall('Never'), type.nullability);
- /// Normalizes `FutureOr` types and emits the normalized version.
- js_ast.Expression _normalizeFutureOr(FutureOrType futureOr) {
+ /// Normalizes `FutureOr` types.
+ ///
+ /// Any changes to the normalization logic here should be mirrored in the
+ /// classes.dart runtime library method named `normalizeFutureOr`.
+ DartType _normalizeFutureOr(FutureOrType futureOr) {
var typeArgument = futureOr.typeArgument;
if (typeArgument is DynamicType) {
// FutureOr<dynamic> --> dynamic
- return visitDynamicType(typeArgument);
+ return typeArgument;
}
if (typeArgument is VoidType) {
// FutureOr<void> --> void
- return visitVoidType(typeArgument);
+ return typeArgument;
}
if (typeArgument is InterfaceType &&
@@ -2744,23 +2755,21 @@
: legacy
? Nullability.legacy
: Nullability.nonNullable;
- return _emitInterfaceType(
- typeArgument.withDeclaredNullability(nullability));
+ return typeArgument.withDeclaredNullability(nullability);
} else if (typeArgument is NeverType) {
// FutureOr<Never> --> Future<Never>
- return _emitInterfaceType(InterfaceType(
- _coreTypes.futureClass, futureOr.nullability, [typeArgument]));
+ return InterfaceType(
+ _coreTypes.futureClass, futureOr.nullability, [typeArgument]);
} else if (typeArgument is NullType) {
// FutureOr<Null> --> Future<Null>?
- return _emitInterfaceType(InterfaceType(
- _coreTypes.futureClass, Nullability.nullable, [typeArgument]));
+ return InterfaceType(
+ _coreTypes.futureClass, Nullability.nullable, [typeArgument]);
} else if (futureOr.declaredNullability == Nullability.nullable &&
typeArgument.nullability == Nullability.nullable) {
// FutureOr<T?>? --> FutureOr<T?>
- return _emitFutureOrType(
- futureOr.withDeclaredNullability(Nullability.nonNullable));
+ return futureOr.withDeclaredNullability(Nullability.nonNullable);
}
- return _emitFutureOrType(futureOr);
+ return futureOr;
}
@override
@@ -2772,8 +2781,12 @@
type.onType.accept(this);
@override
- js_ast.Expression visitFutureOrType(FutureOrType type) =>
- _normalizeFutureOr(type);
+ js_ast.Expression visitFutureOrType(FutureOrType type) {
+ var normalizedType = _normalizeFutureOr(type);
+ return normalizedType is FutureOrType
+ ? _emitFutureOrType(normalizedType)
+ : normalizedType.accept(this);
+ }
/// Emits the representation of [type].
///
diff --git a/runtime/lib/function.cc b/runtime/lib/function.cc
index 07e839f..748e056 100644
--- a/runtime/lib/function.cc
+++ b/runtime/lib/function.cc
@@ -54,6 +54,9 @@
ObjectPtr receiver_a = context_a.At(0);
ObjectPtr receiver_b = context_b.At(0);
if ((receiver_a == receiver_b) &&
+ (!func_a.IsGeneric() ||
+ receiver.delayed_type_arguments() ==
+ other_closure.delayed_type_arguments()) &&
((func_a.ptr() == func_b.ptr()) ||
((func_a.name() == func_b.name()) &&
(func_a.Owner() == func_b.Owner())))) {
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 384b853..b013c63 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -24848,8 +24848,14 @@
uint32_t result = 0;
if (func.IsImplicitInstanceClosureFunction()) {
// Implicit instance closures are not unique, so combine function's hash
- // code with identityHashCode of cached receiver.
+ // code, delayed type arguments hash code (if generic), and identityHashCode
+ // of cached receiver.
result = static_cast<uint32_t>(func.ComputeClosureHash());
+ if (func.IsGeneric()) {
+ const TypeArguments& delayed_type_args =
+ TypeArguments::Handle(zone, delayed_type_arguments());
+ result = CombineHashes(result, delayed_type_args.Hash());
+ }
const Context& context = Context::Handle(zone, this->context());
const Instance& receiver =
Instance::Handle(zone, Instance::RawCast(context.At(0)));
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
index ca02b18..7e019bf 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart
@@ -168,7 +168,6 @@
// this method. This ensures that the we can test a type value returned here
// as a FutureOr because it is equal to 'async.FutureOr` (in the JS).
JS('!', '#[#] = #', genericType, _originalDeclaration, normalize);
- JS('!', '#(#)', addTypeCaches, genericType);
// Add FutureOr specific is and as methods.
is_FutureOr(obj) =>
JS<bool>('!', '#.is(#)', typeArg, obj) ||
@@ -250,7 +249,6 @@
return value;
}
makeGenericType[$_genericTypeCtor] = $typeConstructor;
- $addTypeCaches(makeGenericType);
return makeGenericType;
})()''');
diff --git a/tests/language/generic/regress_45767_test.dart b/tests/language/generic/regress_45767_test.dart
index 953c966..11f9bc3 100644
--- a/tests/language/generic/regress_45767_test.dart
+++ b/tests/language/generic/regress_45767_test.dart
@@ -15,11 +15,27 @@
// Extending F forces DDC to defer the superclass and trigger the bug
class A<T> extends F<A<Object?>> {}
+// Nullability on a type argument in the deferred type.
class B<T> extends F<B<T?>> {}
+// Nullability on a FutureOr in the deferred type.
+class C<T> extends F<C<FutureOr<int>?>> {}
+
+// Reference the current type inside a FutureOr in the deferred type.
+class D<T> extends F<D<FutureOr<D?>>> {}
+
+// Nullability and normalization on FutureOrTypes in the deferred type.
+class G<T> extends F<G<FutureOr<Null>?>> {}
+
void main() {
Expect.isTrue(A<bool>() is I<A<Object?>>);
Expect.equals(!hasSoundNullSafety, A<bool>() is I<A<Object>>);
Expect.isTrue(B<bool>() is I<B<bool?>>);
Expect.equals(!hasSoundNullSafety, B<bool>() is I<B<bool>>);
+ Expect.isTrue(C<bool>() is I<C<FutureOr<int>?>>);
+ Expect.equals(!hasSoundNullSafety, C<bool>() is I<C<FutureOr<int>>>);
+ Expect.isTrue(D<bool>() is I<D<FutureOr<D?>>>);
+ Expect.equals(!hasSoundNullSafety, D<bool>() is I<D<FutureOr<D>>>);
+ Expect.isTrue(G<bool>() is I<G<Future<Null>?>>);
+ Expect.equals(!hasSoundNullSafety, G<bool>() is I<G<Future<Null>>>);
}
diff --git a/tests/language/regress/regress45890_test.dart b/tests/language/regress/regress45890_test.dart
new file mode 100644
index 0000000..abf9a84
--- /dev/null
+++ b/tests/language/regress/regress45890_test.dart
@@ -0,0 +1,16 @@
+// 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 "package:expect/expect.dart";
+
+class C {
+ T foo<T>(T value) => value;
+}
+
+void main() {
+ var c = C();
+ num Function(num) f0 = c.foo;
+ int Function(int) f1 = c.foo;
+ Expect.notEquals(f0, f1);
+}
diff --git a/tests/language_2/regress/regress45890_test.dart b/tests/language_2/regress/regress45890_test.dart
new file mode 100644
index 0000000..abf9a84
--- /dev/null
+++ b/tests/language_2/regress/regress45890_test.dart
@@ -0,0 +1,16 @@
+// 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 "package:expect/expect.dart";
+
+class C {
+ T foo<T>(T value) => value;
+}
+
+void main() {
+ var c = C();
+ num Function(num) f0 = c.foo;
+ int Function(int) f1 = c.foo;
+ Expect.notEquals(f0, f1);
+}
diff --git a/tools/VERSION b/tools/VERSION
index 0fb429d..e356ee5 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 78
+PRERELEASE 79
PRERELEASE_PATCH 0
\ No newline at end of file