Skip to content

Commit

Permalink
Version 2.13.1
Browse files Browse the repository at this point in the history
* Cherry-pick d9f03e9 to stable
* Cherry-pick 5b64d12 to stable
* Cherry-pick ec48e8f to stable
  • Loading branch information
athomas committed May 21, 2021
2 parents 9094f73 + e1c230e commit 375a2d7
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 21 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
62 changes: 43 additions & 19 deletions pkg/dev_compiler/lib/src/kernel/compiler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
/// 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:
///
Expand Down Expand Up @@ -859,22 +862,38 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
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) {
Expand Down Expand Up @@ -921,7 +940,8 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>

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]);
}
Expand Down Expand Up @@ -995,7 +1015,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
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
Expand All @@ -1015,7 +1035,9 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>

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 =
Expand Down Expand Up @@ -1087,7 +1109,7 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
if (shouldDefer(mixinType)) {
deferredSupertypes.add(() => runtimeStatement('applyMixin(#, #)', [
getBaseClass(mixinApplications.length - i),
emitDeferredType(mixinType)
emitDeferredType(mixinType, emitNullability: false)
]));
} else {
body.add(runtimeStatement(
Expand Down Expand Up @@ -2909,7 +2931,9 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
_currentClass != null && identical(_currentClass, _classEmittingExtends);

bool get _cacheTypes =>
!_emittingClassExtends && !_emittingClassSignatures ||
!_emittingDeferredType &&
!_emittingClassExtends &&
!_emittingClassSignatures ||
_currentFunction != null;

js_ast.Expression _emitGenericClassType(
Expand Down
2 changes: 1 addition & 1 deletion sdk/lib/internal/cast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ class CastMap<SK, SV, K, V> extends MapBase<K, V> {
_source.addAll(new CastMap<K, V, SK, SV>(other));
}

V remove(Object? key) => _source.remove(key) as V;
V? remove(Object? key) => _source.remove(key) as V?;

void clear() {
_source.clear();
Expand Down
13 changes: 13 additions & 0 deletions tests/corelib/regress_45473_test.dart
Original file line number Diff line number Diff line change
@@ -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 = <String, dynamic>{"a": null};
var castMap = map.cast<String, Object>();
// Should return `null`, not throw.
Expect.isNull(castMap.remove("b"));
Expect.isNull(castMap.remove("a"));
}
25 changes: 25 additions & 0 deletions tests/language/generic/regress_45767_test.dart
Original file line number Diff line number Diff line change
@@ -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<T> {}

class F<E extends F<E>> extends I<E> {}

// Extending F forces DDC to defer the superclass and trigger the bug
class A<T> extends F<A<Object?>> {}

class B<T> extends F<B<T?>> {}

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>>);
}
2 changes: 1 addition & 1 deletion tools/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@
CHANNEL stable
MAJOR 2
MINOR 13
PATCH 0
PATCH 1
PRERELEASE 0
PRERELEASE_PATCH 0

0 comments on commit 375a2d7

Please sign in to comment.