@@ -7476,7 +7476,7 @@ bool Function::AreValidArguments(NNBDMode mode,
7476
7476
num_named_arguments, error_message)) {
7477
7477
return false;
7478
7478
}
7479
- if (mode != NNBDMode::kLegacyLib ) {
7479
+ if (FLAG_null_safety ) {
7480
7480
// TODO(regis): Check required named arguments.
7481
7481
}
7482
7482
// Verify that all argument names are valid parameter names.
@@ -7844,6 +7844,7 @@ bool Function::HasSameTypeParametersAndBounds(const Function& other,
7844
7844
return false;
7845
7845
}
7846
7846
if (num_type_params > 0) {
7847
+ const NNBDMode mode = nnbd_mode(); // TODO(regis): Remove unused mode.
7847
7848
const TypeArguments& type_params =
7848
7849
TypeArguments::Handle(zone, type_parameters());
7849
7850
ASSERT(!type_params.IsNull());
@@ -7861,8 +7862,16 @@ bool Function::HasSameTypeParametersAndBounds(const Function& other,
7861
7862
ASSERT(bound.IsFinalized());
7862
7863
other_bound = other_type_param.bound();
7863
7864
ASSERT(other_bound.IsFinalized());
7864
- if (!bound.IsEquivalent(other_bound, kind)) {
7865
- return false;
7865
+ if (Dart::non_nullable_flag() && kind == TypeEquality::kInSubtypeTest) {
7866
+ // Bounds that are mutual subtypes are considered equal.
7867
+ if (!bound.IsSubtypeOf(mode, other_bound, Heap::kOld) ||
7868
+ !other_bound.IsSubtypeOf(mode, bound, Heap::kOld)) {
7869
+ return false;
7870
+ }
7871
+ } else {
7872
+ if (!bound.IsEquivalent(other_bound, kind)) {
7873
+ return false;
7874
+ }
7866
7875
}
7867
7876
}
7868
7877
}
@@ -17575,6 +17584,7 @@ bool Instance::NullIsInstanceOf(
17575
17584
ASSERT(!other.IsTypeRef()); // Must be dereferenced at compile time.
17576
17585
// TODO(regis): Verify that the nullability of an instantiated FutureOr
17577
17586
// always matches the nullability of its type argument. For now, be safe.
17587
+ // Also see issue #40123.
17578
17588
AbstractType& type = AbstractType::Handle(other.UnwrapFutureOr());
17579
17589
Nullability nullability = type.nullability();
17580
17590
if (nullability == Nullability::kNullable) {
@@ -17983,6 +17993,55 @@ RawAbstractType* AbstractType::SetInstantiatedNullability(
17983
17993
.SetInstantiatedNullability(type_param, space);
17984
17994
}
17985
17995
17996
+ RawAbstractType* AbstractType::NormalizeInstantiatedType() const {
17997
+ if (Dart::non_nullable_flag()) {
17998
+ // Normalize FutureOr<T>.
17999
+ if (IsFutureOrType()) {
18000
+ const AbstractType& unwrapped_type =
18001
+ AbstractType::Handle(UnwrapFutureOr());
18002
+ const classid_t cid = unwrapped_type.type_class_id();
18003
+ if (cid == kDynamicCid || cid == kVoidCid || cid == kInstanceCid) {
18004
+ return unwrapped_type.raw();
18005
+ }
18006
+ if (cid == kNeverCid && IsNonNullable()) {
18007
+ ObjectStore* object_store = Isolate::Current()->object_store();
18008
+ if (object_store->non_nullable_future_never_type() == Type::null()) {
18009
+ const Class& cls = Class::Handle(object_store->future_class());
18010
+ ASSERT(!cls.IsNull());
18011
+ const TypeArguments& type_args =
18012
+ TypeArguments::Handle(TypeArguments::New(1));
18013
+ type_args.SetTypeAt(0, never_type());
18014
+ Type& type =
18015
+ Type::Handle(Type::New(cls, type_args, TokenPosition::kNoSource,
18016
+ Nullability::kNonNullable));
18017
+ type.SetIsFinalized();
18018
+ type ^= type.Canonicalize();
18019
+ object_store->set_non_nullable_future_never_type(type);
18020
+ }
18021
+ return object_store->non_nullable_future_never_type();
18022
+ }
18023
+ if (cid == kNullCid) {
18024
+ ObjectStore* object_store = Isolate::Current()->object_store();
18025
+ if (object_store->nullable_future_null_type() == Type::null()) {
18026
+ const Class& cls = Class::Handle(object_store->future_class());
18027
+ ASSERT(!cls.IsNull());
18028
+ const TypeArguments& type_args =
18029
+ TypeArguments::Handle(TypeArguments::New(1));
18030
+ Type& type = Type::Handle(object_store->null_type());
18031
+ type_args.SetTypeAt(0, type);
18032
+ type = Type::New(cls, type_args, TokenPosition::kNoSource,
18033
+ Nullability::kNullable);
18034
+ type.SetIsFinalized();
18035
+ type ^= type.Canonicalize();
18036
+ object_store->set_nullable_future_null_type(type);
18037
+ }
18038
+ return object_store->nullable_future_null_type();
18039
+ }
18040
+ }
18041
+ }
18042
+ return raw();
18043
+ }
18044
+
17986
18045
bool AbstractType::IsInstantiated(Genericity genericity,
17987
18046
intptr_t num_free_fun_type_params,
17988
18047
TrailPtr trail) const {
@@ -18395,20 +18454,29 @@ bool AbstractType::IsSubtypeOf(NNBDMode mode,
18395
18454
Heap::Space space) const {
18396
18455
ASSERT(IsFinalized());
18397
18456
ASSERT(other.IsFinalized());
18398
- // Right top type or left bottom type.
18457
+ // Reflexivity.
18458
+ if (raw() == other.raw()) {
18459
+ return true;
18460
+ }
18461
+ // Right top type.
18462
+ if (other.IsTopType()) {
18463
+ return true;
18464
+ }
18465
+ // Left bottom type.
18399
18466
// Any form of Never in weak mode maps to Null and Null is a bottom type in
18400
18467
// weak mode. In strong mode, Never and Never* are bottom types. Therefore,
18401
18468
// Never and Never* are bottom types regardless of weak/strong mode.
18402
- if (other.IsTopType() || (IsNeverType() && !IsNullable())) {
18469
+ // Note that we cannot encounter Never?, as it is normalized to Null.
18470
+ if (IsNeverType()) {
18471
+ ASSERT(!IsNullable());
18403
18472
return true;
18404
18473
}
18474
+ // Left top type.
18405
18475
if (IsDynamicType() || IsVoidType()) {
18406
18476
return false;
18407
18477
}
18408
- // Left Null type, including left Never type mapped to Null.
18409
- // Note that we already handled Never and Never* above.
18410
- // Only Never? remains, which maps to Null regardless of weak/strong mode.
18411
- if (IsNullType() || IsNeverType()) {
18478
+ // Left Null type.
18479
+ if (IsNullType()) {
18412
18480
// In weak mode, Null is a bottom type.
18413
18481
if (!FLAG_null_safety) {
18414
18482
return true;
@@ -18679,6 +18747,10 @@ RawType* Type::ToNullability(Nullability value, Heap::Space space) const {
18679
18747
if (cid == kDynamicCid || cid == kVoidCid || cid == kNullCid) {
18680
18748
return raw();
18681
18749
}
18750
+ if (cid == kNeverCid && value == Nullability::kNullable) {
18751
+ // Normalize Never? to Null.
18752
+ return Type::NullType();
18753
+ }
18682
18754
// Clone type and set new nullability.
18683
18755
Type& type = Type::Handle();
18684
18756
// Always cloning in old space and removing space parameter would not satisfy
@@ -18828,7 +18900,7 @@ RawAbstractType* Type::InstantiateFrom(
18828
18900
}
18829
18901
}
18830
18902
// Canonicalization is not part of instantiation.
18831
- return instantiated_type.raw ();
18903
+ return instantiated_type.NormalizeInstantiatedType ();
18832
18904
}
18833
18905
18834
18906
bool Type::IsEquivalent(const Instance& other,
@@ -19694,9 +19766,10 @@ RawAbstractType* TypeParameter::InstantiateFrom(
19694
19766
if (function_type_arguments.IsNull()) {
19695
19767
return Type::DynamicType();
19696
19768
}
19697
- const AbstractType& result =
19769
+ AbstractType& result =
19698
19770
AbstractType::Handle(function_type_arguments.TypeAt(index()));
19699
- return result.SetInstantiatedNullability(*this, space);
19771
+ result = result.SetInstantiatedNullability(*this, space);
19772
+ return result.NormalizeInstantiatedType();
19700
19773
}
19701
19774
ASSERT(IsClassTypeParameter());
19702
19775
if (instantiator_type_arguments.IsNull()) {
@@ -19711,9 +19784,10 @@ RawAbstractType* TypeParameter::InstantiateFrom(
19711
19784
// (see AssertAssignableInstr::Canonicalize).
19712
19785
return AbstractType::null();
19713
19786
}
19714
- const AbstractType& result =
19787
+ AbstractType& result =
19715
19788
AbstractType::Handle(instantiator_type_arguments.TypeAt(index()));
19716
- return result.SetInstantiatedNullability(*this, space);
19789
+ result = result.SetInstantiatedNullability(*this, space);
19790
+ return result.NormalizeInstantiatedType();
19717
19791
// There is no need to canonicalize the instantiated type parameter, since all
19718
19792
// type arguments are canonicalized at type finalization time. It would be too
19719
19793
// early to canonicalize the returned type argument here, since instantiation
0 commit comments