From 1f16de2096517dda9bb8e1048ac45a9ccb767b96 Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Fri, 21 May 2021 10:42:11 +0000 Subject: [PATCH 1/3] [release] Add release notes for 2.13.1 Change-Id: I896d729e1b6a1b38acc90235ed110ab5f906d6de Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/200874 Reviewed-by: Michael Thomsen --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 844bbba1e057..2575e61ea8a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## 2.13.1 - 2021-05-25 + +This is a patch release that fixes: + +* incorrect behavior in CastMap (issue [#45473][]). +* missing nullability from recursive type hierarchies in DDC (issue [#45767][]). + +[#45473]: https://github.com/dart-lang/sdk/issues/45473 +[#45767]: https://github.com/dart-lang/sdk/issues/45767 + ## 2.13.0 - 2021-05-18 ### Language From 952ed16b79e3bdc1f70fa2578f8c9ae7fe9c7199 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Mon, 10 May 2021 14:15:07 +0000 Subject: [PATCH 2/3] Fix null-safety migration error in CastMap. Make expect use `Never` to signal non-completion instead of depending on `meta`. Change-Id: Ibb4230e6b0cfbf995ad91a31c6620525cf6a8918 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/194244 Reviewed-by: Lasse R.H. Nielsen Reviewed-by: Erik Ernst Reviewed-by: Nate Bosch Commit-Queue: Lasse R.H. Nielsen --- sdk/lib/internal/cast.dart | 2 +- tests/corelib/regress_45473_test.dart | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 tests/corelib/regress_45473_test.dart diff --git a/sdk/lib/internal/cast.dart b/sdk/lib/internal/cast.dart index d99b68710a13..e3e0dae4715a 100644 --- a/sdk/lib/internal/cast.dart +++ b/sdk/lib/internal/cast.dart @@ -277,7 +277,7 @@ class CastMap extends MapBase { _source.addAll(new CastMap(other)); } - V remove(Object? key) => _source.remove(key) as V; + V? remove(Object? key) => _source.remove(key) as V?; void clear() { _source.clear(); diff --git a/tests/corelib/regress_45473_test.dart b/tests/corelib/regress_45473_test.dart new file mode 100644 index 000000000000..4469e13f0aca --- /dev/null +++ b/tests/corelib/regress_45473_test.dart @@ -0,0 +1,13 @@ +// 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"; + +void main() { + var map = {"a": null}; + var castMap = map.cast(); + // Should return `null`, not throw. + Expect.isNull(castMap.remove("b")); + Expect.isNull(castMap.remove("a")); +} From e1c230e6046834b52b60f73c38e9b6a086d15d33 Mon Sep 17 00:00:00 2001 From: Nicholas Shahan Date: Mon, 3 May 2021 17:54:19 +0000 Subject: [PATCH 3/3] [ddc] Fix missing nullability on deferred types Emits legacy and nullable wrappers to the types that appear in circular hierarchies. There is still missing nullability information if FutureOr appears in the type hierarchy but that fix uncovers a larger issue with the FutureOr type. See https://github.com/dart-lang/sdk/issues/45870. Change-Id: If5894eaff632c5a961f1316d8803032fae2a0ec5 Fixes: https://github.com/dart-lang/sdk/issues/45767 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196600 Commit-Queue: Nicholas Shahan Reviewed-by: Sigmund Cherem Reviewed-by: Mark Zhou --- pkg/dev_compiler/lib/src/kernel/compiler.dart | 62 +++++++++++++------ .../language/generic/regress_45767_test.dart | 25 ++++++++ 2 files changed, 68 insertions(+), 19 deletions(-) create mode 100644 tests/language/generic/regress_45767_test.dart diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart index a01a3b90dc95..84bfd17056f9 100644 --- a/pkg/dev_compiler/lib/src/kernel/compiler.dart +++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart @@ -94,6 +94,9 @@ class ProgramCompiler extends ComputeOnceConstantVisitor /// The class that is emitting its signature information, otherwise null. Class _classEmittingSignatures; + /// True when a class is emitting a deferred class hierarchy. + bool _emittingDeferredType = false; + /// The current element being loaded. /// We can use this to determine if we're loading top-level code or not: /// @@ -859,22 +862,38 @@ class ProgramCompiler extends ComputeOnceConstantVisitor return; } - js_ast.Expression emitDeferredType(DartType t) { - assert(isKnownDartTypeImplementor(t)); - if (t is InterfaceType) { - _declareBeforeUse(t.classNode); - if (t.typeArguments.isNotEmpty) { - return _emitGenericClassType( - t, t.typeArguments.map(emitDeferredType)); + js_ast.Expression emitDeferredType(DartType t, + {bool emitNullability = true}) { + js_ast.Expression _emitDeferredType(DartType t, + {bool emitNullability = true}) { + if (t is InterfaceType) { + _declareBeforeUse(t.classNode); + if (t.typeArguments.isNotEmpty) { + var typeRep = _emitGenericClassType( + t, t.typeArguments.map(_emitDeferredType)); + return emitNullability + ? _emitNullabilityWrapper(typeRep, t.declaredNullability) + : typeRep; + } + 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)); + } else if (t is TypeParameterType) { + return _emitTypeParameterType(t, emitNullability: emitNullability); } - return _emitInterfaceType(t, emitNullability: false); - } else if (t is FutureOrType) { - _declareBeforeUse(_coreTypes.deprecatedFutureOrClass); - return _emitFutureOrTypeWithArgument(emitDeferredType(t.typeArgument)); - } else if (t is TypeParameterType) { - return _emitTypeParameterType(t, emitNullability: false); + return _emitType(t); } - return _emitType(t); + + assert(isKnownDartTypeImplementor(t)); + var savedEmittingDeferredType = _emittingDeferredType; + _emittingDeferredType = true; + var deferredClassRep = + _emitDeferredType(t, emitNullability: emitNullability); + _emittingDeferredType = savedEmittingDeferredType; + return deferredClassRep; } bool shouldDefer(InterfaceType t) { @@ -921,7 +940,8 @@ class ProgramCompiler extends ComputeOnceConstantVisitor js_ast.Expression getBaseClass(int count) { var base = emitDeferredType( - c.getThisType(_coreTypes, c.enclosingLibrary.nonNullable)); + c.getThisType(_coreTypes, c.enclosingLibrary.nonNullable), + emitNullability: false); while (--count >= 0) { base = js.call('#.__proto__', [base]); } @@ -995,7 +1015,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor var originalSupertype = supertype; deferredSupertypes.add(() => runtimeStatement('setBaseClass(#, #)', [ getBaseClass(isMixinAliasClass(c) ? 0 : mixinApplications.length), - emitDeferredType(originalSupertype), + emitDeferredType(originalSupertype, emitNullability: false), ])); // Refers to 'supertype' without type parameters. We remove these from // the 'extends' clause for generics for cyclic dependencies and append @@ -1015,7 +1035,9 @@ class ProgramCompiler extends ComputeOnceConstantVisitor var m = c.mixedInType.asInterfaceType; var deferMixin = shouldDefer(m); - var mixinClass = deferMixin ? emitDeferredType(m) : emitClassRef(m); + var mixinClass = deferMixin + ? emitDeferredType(m, emitNullability: false) + : emitClassRef(m); var classExpr = deferMixin ? getBaseClass(0) : className; var mixinApplication = @@ -1087,7 +1109,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor if (shouldDefer(mixinType)) { deferredSupertypes.add(() => runtimeStatement('applyMixin(#, #)', [ getBaseClass(mixinApplications.length - i), - emitDeferredType(mixinType) + emitDeferredType(mixinType, emitNullability: false) ])); } else { body.add(runtimeStatement( @@ -2909,7 +2931,9 @@ class ProgramCompiler extends ComputeOnceConstantVisitor _currentClass != null && identical(_currentClass, _classEmittingExtends); bool get _cacheTypes => - !_emittingClassExtends && !_emittingClassSignatures || + !_emittingDeferredType && + !_emittingClassExtends && + !_emittingClassSignatures || _currentFunction != null; js_ast.Expression _emitGenericClassType( diff --git a/tests/language/generic/regress_45767_test.dart b/tests/language/generic/regress_45767_test.dart new file mode 100644 index 000000000000..953c966404d7 --- /dev/null +++ b/tests/language/generic/regress_45767_test.dart @@ -0,0 +1,25 @@ +// 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'; + +import 'package:expect/expect.dart'; + +// Regression test for https://github.com/dart-lang/sdk/issues/45767. + +class I {} + +class F> extends I {} + +// Extending F forces DDC to defer the superclass and trigger the bug +class A extends F> {} + +class B extends F> {} + +void main() { + Expect.isTrue(A() is I>); + Expect.equals(!hasSoundNullSafety, A() is I>); + Expect.isTrue(B() is I>); + Expect.equals(!hasSoundNullSafety, B() is I>); +}