mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 12:57:42 +00:00
[ddc] Fix bug in FutureOr type normalization
The correct normalization should only normalize FutureOr<Never> when Never is non-nullable. Change-Id: I592f3a4856c219b33a8f1ac8377567a956e1148c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/261000 Commit-Queue: Nicholas Shahan <nshahan@google.com> Reviewed-by: Mayank Patke <fishythefish@google.com> Reviewed-by: Erik Ernst <eernst@google.com>
This commit is contained in:
parent
118f628ecf
commit
da79baa962
|
@ -4337,7 +4337,9 @@ AbstractBool _typeTest(
|
|||
bool _nullIs(DartType /*!*/ type) =>
|
||||
dartTypes.isStrongTopType(type) ||
|
||||
type is LegacyType &&
|
||||
(type.baseType.isObject || type.baseType is NeverType) ||
|
||||
(type.baseType.isObject ||
|
||||
type.baseType is NeverType ||
|
||||
_nullIs(type.baseType)) ||
|
||||
type is NullableType ||
|
||||
type is FutureOrType && _nullIs(type.typeArgument) ||
|
||||
type.isNull;
|
||||
|
|
|
@ -59,7 +59,7 @@ class _FutureOrNormalizer extends ReplacementVisitor {
|
|||
? Nullability.legacy
|
||||
: Nullability.nonNullable;
|
||||
return typeArgument.withDeclaredNullability(nullability);
|
||||
} else if (typeArgument is NeverType) {
|
||||
} else if (typeArgument == const NeverType.nonNullable()) {
|
||||
// FutureOr<Never> --> Future<Never>
|
||||
return InterfaceType(
|
||||
_coreTypes.futureClass, futureOr.nullability, [typeArgument]);
|
||||
|
|
|
@ -382,9 +382,12 @@ class LegacyType extends DartType {
|
|||
@JSExportName('is')
|
||||
bool is_T(obj) {
|
||||
if (obj == null) {
|
||||
// Object and Never are the only legacy types that should return true if
|
||||
// Object and Never are trivially legacy types that should return true if
|
||||
// obj is `null`.
|
||||
return _equalType(type, Object) || _equalType(type, Never);
|
||||
if (_equalType(type, Object) || _equalType(type, Never)) return true;
|
||||
|
||||
return _isFutureOr(type) &&
|
||||
JS<bool>('!', '#[0].is(#)', getGenericArgs(type), obj);
|
||||
}
|
||||
return JS<bool>('!', '#.is(#)', type, obj);
|
||||
}
|
||||
|
@ -1383,7 +1386,7 @@ external Type legacyTypeRep<T>();
|
|||
@notNull
|
||||
bool _isFutureOr(type) {
|
||||
var genericClass = getGenericClass(type);
|
||||
return JS<bool>('!', '# && # === #', genericClass, genericClass,
|
||||
return JS<bool>('!', '!!# && # === #', genericClass, genericClass,
|
||||
getGenericClassStatic<FutureOr>());
|
||||
}
|
||||
|
||||
|
|
|
@ -933,6 +933,7 @@ bool _nullIs(Rti testRti) {
|
|||
isLegacyObjectType(testRti) ||
|
||||
_Utils.isIdentical(testRti, LEGACY_TYPE_REF<Never>()) ||
|
||||
kind == Rti.kindQuestion ||
|
||||
kind == Rti.kindStar && _nullIs(Rti._getStarArgument(testRti)) ||
|
||||
kind == Rti.kindFutureOr && _nullIs(Rti._getFutureOrArgument(testRti)) ||
|
||||
isNullType(testRti);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright (c) 2022, 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.
|
||||
|
||||
// @dart=2.7
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
import 'future_or_never_normalization_test.dart';
|
||||
|
||||
@pragma('dart2js:noInline')
|
||||
bool legacyTypeTest<T>(dynamic val) => val is T;
|
||||
|
||||
@pragma('dart2js:noInline')
|
||||
bool legacyFutureOrTypeTest<T>(dynamic val) => val is FutureOr<T>;
|
||||
|
||||
void weakTests() {
|
||||
Expect.isTrue(typeTest<FutureOr<Never>>(null));
|
||||
Expect.isTrue(futureOrTypeTest<Never>(null));
|
||||
Expect.isTrue(legacyFutureOrTypeTest<Never>(null));
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2022, 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.
|
||||
|
||||
// Requirements=nnbd-weak
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
import 'future_or_never_normalization_legacy_lib.dart';
|
||||
|
||||
// Tests to ensure normalization of various forms of FutureOr<Never> include
|
||||
// or exclude null properly.
|
||||
|
||||
@pragma('dart2js:noInline')
|
||||
bool typeTest<T>(dynamic val) => val is T;
|
||||
|
||||
@pragma('dart2js:noInline')
|
||||
bool futureOrTypeTest<T>(dynamic val) => val is FutureOr<T>;
|
||||
|
||||
void main() {
|
||||
Expect.isTrue(typeTest<FutureOr<Never?>>(null));
|
||||
Expect.isTrue(futureOrTypeTest<Never?>(null));
|
||||
Expect.isTrue(legacyFutureOrTypeTest<Never?>(null));
|
||||
Expect.isFalse(typeTest<FutureOr<Never>>(null));
|
||||
Expect.isFalse(legacyTypeTest<FutureOr<Never>>(null));
|
||||
Expect.isFalse(futureOrTypeTest<Never>(null));
|
||||
Expect.isTrue(legacyFutureOrTypeTest<Never>(null));
|
||||
weakTests();
|
||||
}
|
Loading…
Reference in a new issue