[vm] Unsound mode cleanup: remove legacy types from the VM

TEST=ci

Change-Id: I0ade9ebf5dff2b283a2c7e0ff99dc6b56f548ba9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/364622
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
This commit is contained in:
Alexander Markov 2024-04-30 17:49:37 +00:00 committed by Commit Queue
parent dced438e75
commit 6e5aae8e0f
37 changed files with 909 additions and 1554 deletions

View file

@ -4,6 +4,9 @@
- The Dart VM only executes sound null safe code, running of unsound null
safe code using the option `--no-sound-null-safety` has been removed.
- `Dart_NewListOf` and `Dart_IsLegacyType` functions are
removed from Dart C API.
## 3.4.0
### Language

View file

@ -2420,25 +2420,6 @@ DART_EXPORT Dart_Handle Dart_StringGetProperties(Dart_Handle str,
*/
DART_EXPORT Dart_Handle Dart_NewList(intptr_t length);
typedef enum {
Dart_CoreType_Dynamic,
Dart_CoreType_Int,
Dart_CoreType_String,
} Dart_CoreType_Id;
// TODO(bkonyi): convert this to use nullable types once NNBD is enabled.
/**
* Returns a List of the desired length with the desired legacy element type.
*
* \param element_type_id The type of elements of the list.
* \param length The length of the list.
*
* \return The List object if no error occurs. Otherwise returns an error
* handle.
*/
DART_EXPORT Dart_Handle Dart_NewListOf(Dart_CoreType_Id element_type_id,
intptr_t length);
/**
* Returns a List of the desired length with the desired element type.
*
@ -3590,7 +3571,6 @@ DART_EXPORT Dart_Handle Dart_TypeToNonNullableType(Dart_Handle type);
*/
DART_EXPORT Dart_Handle Dart_IsNullableType(Dart_Handle type, bool* result);
DART_EXPORT Dart_Handle Dart_IsNonNullableType(Dart_Handle type, bool* result);
DART_EXPORT Dart_Handle Dart_IsLegacyType(Dart_Handle type, bool* result);
/**
* Lookup a class or interface by name from a Library.

View file

@ -216,7 +216,7 @@ static InstancePtr CreateTypeVariableList(const Class& cls) {
TypeParameter& type = TypeParameter::Handle();
String& name = String::Handle();
for (intptr_t i = 0; i < num_type_params; i++) {
type = cls.TypeParameterAt(i, Nullability::kLegacy);
type = cls.TypeParameterAt(i, Nullability::kNonNullable);
ASSERT(type.IsFinalized());
name = type.UserVisibleName();
result.SetAt(2 * i, name);
@ -544,21 +544,21 @@ static InstancePtr CreateTypeMirror(const AbstractType& type) {
args.SetAt(0, Symbols::Never());
return CreateMirror(Symbols::_SpecialTypeMirror(), args);
}
// TODO(regis): Until mirrors reflect nullability, force kLegacy, except for
// Null type, which should remain nullable.
// TODO(regis): Until mirrors reflect nullability, force kNonNullable,
// except for Null type, which should remain nullable.
if (!type.IsNullType()) {
Type& legacy_type = Type::Handle(
Type::Cast(type).ToNullability(Nullability::kLegacy, Heap::kOld));
Type& legacy_type = Type::Handle(Type::Cast(type).ToNullability(
Nullability::kNonNullable, Heap::kOld));
legacy_type ^= legacy_type.Canonicalize(Thread::Current());
return CreateClassMirror(cls, legacy_type, Bool::False(),
Object::null_instance());
}
return CreateClassMirror(cls, type, Bool::False(), Object::null_instance());
} else if (type.IsTypeParameter()) {
// TODO(regis): Until mirrors reflect nullability, force kLegacy.
// TODO(regis): Until mirrors reflect nullability, force kNonNullable.
TypeParameter& legacy_type =
TypeParameter::Handle(TypeParameter::Cast(type).ToNullability(
Nullability::kLegacy, Heap::kOld));
Nullability::kNonNullable, Heap::kOld));
legacy_type ^= legacy_type.Canonicalize(Thread::Current());
return CreateTypeVariableMirror(legacy_type, Object::null_instance());
}

View file

@ -175,7 +175,6 @@ main() {
"Dart_IsInteger",
"Dart_IsKernel",
"Dart_IsKernelIsolate",
"Dart_IsLegacyType",
"Dart_IsLibrary",
"Dart_IsList",
"Dart_IsMap",
@ -244,7 +243,6 @@ main() {
"Dart_NewIntegerFromHexCString",
"Dart_NewIntegerFromUint64",
"Dart_NewList",
"Dart_NewListOf",
"Dart_NewListOfType",
"Dart_NewListOfTypeFilled",
"Dart_NewNativePort",

View file

@ -1201,7 +1201,7 @@ void AsmIntrinsifier::String_getHashCode(Assembler* assembler,
void AsmIntrinsifier::Type_equality(Assembler* assembler,
Label* normal_ir_body) {
Label equal, not_equal, equiv_cids_may_be_generic, equiv_cids, check_legacy;
Label equal, not_equal, equiv_cids_may_be_generic, equiv_cids;
__ ldm(IA, SP, (1 << R1 | 1 << R2));
__ cmp(R1, Operand(R2));
@ -1234,24 +1234,13 @@ void AsmIntrinsifier::Type_equality(Assembler* assembler,
__ LoadAbstractTypeNullability(R1, R1);
__ LoadAbstractTypeNullability(R2, R2);
__ cmp(R1, Operand(R2));
__ b(&check_legacy, NE);
// Fall through to equal case if nullability is strictly equal.
__ b(&not_equal, NE);
// Fall through to equal case if nullability is equal.
__ Bind(&equal);
__ LoadObject(R0, CastHandle<Object>(TrueObject()));
__ Ret();
// At this point the nullabilities are different, so they can only be
// syntactically equivalent if they're both either kNonNullable or kLegacy.
// These are the two largest values of the enum, so we can just do a < check.
ASSERT(target::Nullability::kNullable < target::Nullability::kNonNullable &&
target::Nullability::kNonNullable < target::Nullability::kLegacy);
__ Bind(&check_legacy);
__ CompareImmediate(R1, target::Nullability::kNonNullable);
__ b(&not_equal, LT);
__ CompareImmediate(R2, target::Nullability::kNonNullable);
__ b(&equal, GE);
__ Bind(&not_equal);
__ LoadObject(R0, CastHandle<Object>(FalseObject()));
__ Ret();

View file

@ -1361,7 +1361,7 @@ void AsmIntrinsifier::String_getHashCode(Assembler* assembler,
void AsmIntrinsifier::Type_equality(Assembler* assembler,
Label* normal_ir_body) {
Label equal, not_equal, equiv_cids_may_be_generic, equiv_cids, check_legacy;
Label equal, not_equal, equiv_cids_may_be_generic, equiv_cids;
__ ldp(R1, R2, Address(SP, 0 * target::kWordSize, Address::PairOffset));
__ CompareObjectRegisters(R1, R2);
@ -1394,24 +1394,13 @@ void AsmIntrinsifier::Type_equality(Assembler* assembler,
__ LoadAbstractTypeNullability(R1, R1);
__ LoadAbstractTypeNullability(R2, R2);
__ cmp(R1, Operand(R2));
__ b(&check_legacy, NE);
// Fall through to equal case if nullability is strictly equal.
__ b(&not_equal, NE);
// Fall through to equal case if nullability is equal.
__ Bind(&equal);
__ LoadObject(R0, CastHandle<Object>(TrueObject()));
__ ret();
// At this point the nullabilities are different, so they can only be
// syntactically equivalent if they're both either kNonNullable or kLegacy.
// These are the two largest values of the enum, so we can just do a < check.
ASSERT(target::Nullability::kNullable < target::Nullability::kNonNullable &&
target::Nullability::kNonNullable < target::Nullability::kLegacy);
__ Bind(&check_legacy);
__ CompareImmediate(R1, target::Nullability::kNonNullable);
__ b(&not_equal, LT);
__ CompareImmediate(R2, target::Nullability::kNonNullable);
__ b(&equal, GE);
__ Bind(&not_equal);
__ LoadObject(R0, CastHandle<Object>(FalseObject()));
__ ret();

View file

@ -1342,7 +1342,7 @@ void AsmIntrinsifier::String_getHashCode(Assembler* assembler,
void AsmIntrinsifier::Type_equality(Assembler* assembler,
Label* normal_ir_body) {
Label equal, not_equal, equiv_cids_may_be_generic, equiv_cids, check_legacy;
Label equal, not_equal, equiv_cids_may_be_generic, equiv_cids;
__ movl(EDI, Address(ESP, +1 * target::kWordSize));
__ movl(EBX, Address(ESP, +2 * target::kWordSize));
@ -1376,24 +1376,13 @@ void AsmIntrinsifier::Type_equality(Assembler* assembler,
__ LoadAbstractTypeNullability(EDI, EDI);
__ LoadAbstractTypeNullability(EBX, EBX);
__ cmpl(EDI, EBX);
__ j(NOT_EQUAL, &check_legacy, Assembler::kNearJump);
__ j(NOT_EQUAL, &not_equal, Assembler::kNearJump);
// Fall through to equal case if nullability is strictly equal.
__ Bind(&equal);
__ LoadObject(EAX, CastHandle<Object>(TrueObject()));
__ ret();
// At this point the nullabilities are different, so they can only be
// syntactically equivalent if they're both either kNonNullable or kLegacy.
// These are the two largest values of the enum, so we can just do a < check.
ASSERT(target::Nullability::kNullable < target::Nullability::kNonNullable &&
target::Nullability::kNonNullable < target::Nullability::kLegacy);
__ Bind(&check_legacy);
__ cmpl(EDI, Immediate(target::Nullability::kNonNullable));
__ j(LESS, &not_equal, Assembler::kNearJump);
__ cmpl(EBX, Immediate(target::Nullability::kNonNullable));
__ j(GREATER_EQUAL, &equal, Assembler::kNearJump);
__ Bind(&not_equal);
__ LoadObject(EAX, CastHandle<Object>(FalseObject()));
__ ret();

View file

@ -1398,7 +1398,7 @@ void AsmIntrinsifier::String_getHashCode(Assembler* assembler,
void AsmIntrinsifier::Type_equality(Assembler* assembler,
Label* normal_ir_body) {
Label equal, not_equal, equiv_cids_may_be_generic, equiv_cids, check_legacy;
Label equal, not_equal, equiv_cids_may_be_generic, equiv_cids;
__ lx(A0, Address(SP, 1 * target::kWordSize));
__ lx(A1, Address(SP, 0 * target::kWordSize));
@ -1430,24 +1430,13 @@ void AsmIntrinsifier::Type_equality(Assembler* assembler,
__ Bind(&equiv_cids);
__ LoadAbstractTypeNullability(A0, A0);
__ LoadAbstractTypeNullability(A1, A1);
__ bne(A0, A1, &check_legacy);
// Fall through to equal case if nullability is strictly equal.
__ bne(A0, A1, &not_equal);
// Fall through to equal case if nullability is equal.
__ Bind(&equal);
__ LoadObject(A0, CastHandle<Object>(TrueObject()));
__ ret();
// At this point the nullabilities are different, so they can only be
// syntactically equivalent if they're both either kNonNullable or kLegacy.
// These are the two largest values of the enum, so we can just do a < check.
ASSERT(target::Nullability::kNullable < target::Nullability::kNonNullable &&
target::Nullability::kNonNullable < target::Nullability::kLegacy);
__ Bind(&check_legacy);
__ CompareImmediate(A1, target::Nullability::kNonNullable);
__ BranchIf(LT, &not_equal);
__ CompareImmediate(A0, target::Nullability::kNonNullable);
__ BranchIf(GE, &equal);
__ Bind(&not_equal);
__ LoadObject(A0, CastHandle<Object>(FalseObject()));
__ ret();

View file

@ -1282,24 +1282,13 @@ void AsmIntrinsifier::Type_equality(Assembler* assembler,
__ LoadAbstractTypeNullability(RCX, RCX);
__ LoadAbstractTypeNullability(RDX, RDX);
__ cmpq(RCX, RDX);
__ j(NOT_EQUAL, &check_legacy, Assembler::kNearJump);
// Fall through to equal case if nullability is strictly equal.
__ j(NOT_EQUAL, &not_equal, Assembler::kNearJump);
// Fall through to equal case if nullability is equal.
__ Bind(&equal);
__ LoadObject(RAX, CastHandle<Object>(TrueObject()));
__ ret();
// At this point the nullabilities are different, so they can only be
// syntactically equivalent if they're both either kNonNullable or kLegacy.
// These are the two largest values of the enum, so we can just do a < check.
ASSERT(target::Nullability::kNullable < target::Nullability::kNonNullable &&
target::Nullability::kNonNullable < target::Nullability::kLegacy);
__ Bind(&check_legacy);
__ cmpq(RCX, Immediate(target::Nullability::kNonNullable));
__ j(LESS, &not_equal, Assembler::kNearJump);
__ cmpq(RDX, Immediate(target::Nullability::kNonNullable));
__ j(GREATER_EQUAL, &equal, Assembler::kNearJump);
__ Bind(&not_equal);
__ LoadObject(RAX, CastHandle<Object>(FalseObject()));
__ ret();

View file

@ -2723,10 +2723,7 @@ void FlowGraphCompiler::GenerateInstanceOf(const InstructionSource& source,
// See NullIsInstanceOf().
__ CompareObject(TypeTestABI::kInstanceReg, Object::null_object());
__ BranchIf(EQUAL,
(unwrapped_type.IsNullable() ||
(unwrapped_type.IsLegacy() && unwrapped_type.IsNeverType()))
? &is_instance
: &is_not_instance);
unwrapped_type.IsNullable() ? &is_instance : &is_not_instance);
}
// Generate inline instanceof test.

View file

@ -6102,12 +6102,6 @@ void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
? StubCode::InstantiateTypeNullableFunctionTypeParameter().ptr()
: StubCode::InstantiateTypeNullableClassTypeParameter().ptr();
break;
case Nullability::kLegacy:
stub =
is_function_parameter
? StubCode::InstantiateTypeLegacyFunctionTypeParameter().ptr()
: StubCode::InstantiateTypeLegacyClassTypeParameter().ptr();
break;
}
}
__ LoadObject(InstantiateTypeABI::kTypeReg, type());

View file

@ -47,15 +47,14 @@ ISOLATE_UNIT_TEST_CASE(OptimizationTests) {
}
ISOLATE_UNIT_TEST_CASE(IRTest_EliminateWriteBarrier) {
const char* nullable_tag = TestCase::NullableTag();
// clang-format off
auto kScript = Utils::CStringUniquePtr(OS::SCreate(nullptr, R"(
const char* kScript = R"(
class Container<T> {
operator []=(var index, var value) {
return data[index] = value;
}
List<T%s> data = List<T%s>.filled(10, null);
List<T?> data = List<T?>.filled(10, null);
}
Container<int> x = Container<int>();
@ -65,10 +64,10 @@ ISOLATE_UNIT_TEST_CASE(IRTest_EliminateWriteBarrier) {
x[i] = i;
}
}
)", nullable_tag, nullable_tag), std::free);
)";
// clang-format on
const auto& root_library = Library::Handle(LoadTestScript(kScript.get()));
const auto& root_library = Library::Handle(LoadTestScript(kScript));
const auto& function = Function::Handle(GetFunction(root_library, "foo"));
Invoke(root_library, "foo");
@ -133,7 +132,7 @@ static void RunInitializingStoresTest(
ISOLATE_UNIT_TEST_CASE(IRTest_InitializingStores) {
// clang-format off
auto kScript = Utils::CStringUniquePtr(OS::SCreate(nullptr, R"(
const char* kScript = R"(
class Bar {
var f;
var g;
@ -145,7 +144,7 @@ ISOLATE_UNIT_TEST_CASE(IRTest_InitializingStores) {
f3() {
return () { };
}
f4<T>({T%s value}) {
f4<T>({T? value}) {
return () { return value; };
}
main() {
@ -154,11 +153,10 @@ ISOLATE_UNIT_TEST_CASE(IRTest_InitializingStores) {
f3();
f4();
}
)",
TestCase::NullableTag()), std::free);
)";
// clang-format on
const auto& root_library = Library::Handle(LoadTestScript(kScript.get()));
const auto& root_library = Library::Handle(LoadTestScript(kScript));
Invoke(root_library, "main");
RunInitializingStoresTest(root_library, "f1", CompilerPass::kJIT,

View file

@ -16,15 +16,13 @@ namespace dart {
ISOLATE_UNIT_TEST_CASE(ReachabilityFence_Simple) {
// clang-format off
auto kScript =
Utils::CStringUniquePtr(OS::SCreate(nullptr,
R"(
const char* kScript = R"(
import 'dart:_internal' show reachabilityFence;
int someGlobal = 0;
class A {
int%s a;
int? a;
}
void someFunction(int arg) {
@ -33,14 +31,13 @@ ISOLATE_UNIT_TEST_CASE(ReachabilityFence_Simple) {
main() {
final object = A()..a = 10;
someFunction(object.a%s);
someFunction(object.a!);
reachabilityFence(object);
}
)",
TestCase::NullableTag(), TestCase::NullAssertTag()), std::free);
)";
// clang-format on
const auto& root_library = Library::Handle(LoadTestScript(kScript.get()));
const auto& root_library = Library::Handle(LoadTestScript(kScript));
Invoke(root_library, "main");
@ -76,14 +73,13 @@ ISOLATE_UNIT_TEST_CASE(ReachabilityFence_Simple) {
ISOLATE_UNIT_TEST_CASE(ReachabilityFence_Loop) {
// clang-format off
auto kScript =
Utils::CStringUniquePtr(OS::SCreate(nullptr, R"(
const char* kScript = R"(
import 'dart:_internal' show reachabilityFence;
int someGlobal = 0;
class A {
int%s a;
int? a;
}
@pragma('vm:never-inline')
@ -98,14 +94,14 @@ ISOLATE_UNIT_TEST_CASE(ReachabilityFence_Loop) {
main() {
final object = makeSomeA();
for(int i = 0; i < 100000; i++) {
someFunction(object.a%s);
someFunction(object.a!);
reachabilityFence(object);
}
}
)", TestCase::NullableTag(), TestCase::NullAssertTag()), std::free);
)";
// clang-format on
const auto& root_library = Library::Handle(LoadTestScript(kScript.get()));
const auto& root_library = Library::Handle(LoadTestScript(kScript));
Invoke(root_library, "main");
@ -141,14 +137,13 @@ ISOLATE_UNIT_TEST_CASE(ReachabilityFence_Loop) {
ISOLATE_UNIT_TEST_CASE(ReachabilityFence_NoCanonicalize) {
// clang-format off
auto kScript =
Utils::CStringUniquePtr(OS::SCreate(nullptr, R"(
const char* kScript = R"(
import 'dart:_internal' show reachabilityFence;
int someGlobal = 0;
class A {
int%s a;
int? a;
}
@pragma('vm:never-inline')
@ -164,16 +159,16 @@ ISOLATE_UNIT_TEST_CASE(ReachabilityFence_NoCanonicalize) {
final object = makeSomeA();
reachabilityFence(object);
for(int i = 0; i < 100000; i++) {
someFunction(object.a%s);
someFunction(object.a!);
reachabilityFence(object);
}
reachabilityFence(object);
reachabilityFence(object);
}
)", TestCase::NullableTag(), TestCase::NullAssertTag()), std::free);
)";
// clang-format on
const auto& root_library = Library::Handle(LoadTestScript(kScript.get()));
const auto& root_library = Library::Handle(LoadTestScript(kScript));
Invoke(root_library, "main");

View file

@ -1013,10 +1013,6 @@ ISOLATE_UNIT_TEST_CASE(LoadOptimizer_RedundantInitializerCallAfterIf) {
}
ISOLATE_UNIT_TEST_CASE(LoadOptimizer_RedundantInitializerCallInLoop) {
if (!TestCase::IsNNBD()) {
return;
}
const char* kScript = R"(
class A {
late int x = int.parse('1');

View file

@ -425,8 +425,7 @@ void FlowGraphTypePropagator::VisitBranch(BranchInstr* instr) {
left = instance_of->value()->definition();
}
if (!type->IsTopTypeForInstanceOf()) {
const bool is_nullable = (type->IsNullable() || type->IsTypeParameter() ||
(type->IsNeverType() && type->IsLegacy()))
const bool is_nullable = (type->IsNullable() || type->IsTypeParameter())
? CompileType::kCanBeNull
: CompileType::kCannotBeNull;
EnsureMoreAccurateRedefinition(

View file

@ -400,9 +400,7 @@ ISOLATE_UNIT_TEST_CASE(TypePropagator_Regress36156) {
ISOLATE_UNIT_TEST_CASE(CompileType_CanBeSmi) {
CompilerState S(thread, /*is_aot=*/false, /*is_optimizing=*/true);
const char* late_tag = TestCase::LateTag();
auto script_chars = Utils::CStringUniquePtr(
OS::SCreate(nullptr, R"(
const char* script_chars = R"(
import 'dart:async';
class G<T> {}
@ -412,50 +410,44 @@ class C<NoBound,
ComparableBound extends Comparable,
StringBound extends String> {
// Simple instantiated types.
@pragma('vm-test:can-be-smi') %s int t1;
@pragma('vm-test:can-be-smi') %s num t2;
@pragma('vm-test:can-be-smi') %s Object t3;
%s String t4;
@pragma('vm-test:can-be-smi') late int t1;
@pragma('vm-test:can-be-smi') late num t2;
@pragma('vm-test:can-be-smi') late Object t3;
late String t4;
// Type parameters.
@pragma('vm-test:can-be-smi') %s NoBound tp1;
@pragma('vm-test:can-be-smi') %s NumBound tp2;
@pragma('vm-test:can-be-smi') %s ComparableBound tp3;
%s StringBound tp4;
@pragma('vm-test:can-be-smi') late NoBound tp1;
@pragma('vm-test:can-be-smi') late NumBound tp2;
@pragma('vm-test:can-be-smi') late ComparableBound tp3;
late StringBound tp4;
// Comparable<T> instantiations.
@pragma('vm-test:can-be-smi') %s Comparable c1;
%s Comparable<String> c2;
@pragma('vm-test:can-be-smi') %s Comparable<num> c3;
%s Comparable<int> c4; // int is not a subtype of Comparable<int>.
@pragma('vm-test:can-be-smi') %s Comparable<NoBound> c5;
@pragma('vm-test:can-be-smi') %s Comparable<NumBound> c6;
@pragma('vm-test:can-be-smi') %s Comparable<ComparableBound> c7;
%s Comparable<StringBound> c8;
@pragma('vm-test:can-be-smi') late Comparable c1;
late Comparable<String> c2;
@pragma('vm-test:can-be-smi') late Comparable<num> c3;
late Comparable<int> c4; // int is not a subtype of Comparable<int>.
@pragma('vm-test:can-be-smi') late Comparable<NoBound> c5;
@pragma('vm-test:can-be-smi') late Comparable<NumBound> c6;
@pragma('vm-test:can-be-smi') late Comparable<ComparableBound> c7;
late Comparable<StringBound> c8;
// FutureOr<T> instantiations.
@pragma('vm-test:can-be-smi') %s FutureOr fo1;
%s FutureOr<String> fo2;
@pragma('vm-test:can-be-smi') %s FutureOr<num> fo3;
@pragma('vm-test:can-be-smi') %s FutureOr<int> fo4;
@pragma('vm-test:can-be-smi') %s FutureOr<NoBound> fo5;
@pragma('vm-test:can-be-smi') %s FutureOr<NumBound> fo6;
@pragma('vm-test:can-be-smi') %s FutureOr<ComparableBound> fo7;
%s FutureOr<StringBound> fo8;
@pragma('vm-test:can-be-smi') late FutureOr fo1;
late FutureOr<String> fo2;
@pragma('vm-test:can-be-smi') late FutureOr<num> fo3;
@pragma('vm-test:can-be-smi') late FutureOr<int> fo4;
@pragma('vm-test:can-be-smi') late FutureOr<NoBound> fo5;
@pragma('vm-test:can-be-smi') late FutureOr<NumBound> fo6;
@pragma('vm-test:can-be-smi') late FutureOr<ComparableBound> fo7;
late FutureOr<StringBound> fo8;
// Other generic classes.
%s G<int> g1;
%s G<NoBound> g2;
late G<int> g1;
late G<NoBound> g2;
}
)",
late_tag, late_tag, late_tag, late_tag, late_tag, late_tag,
late_tag, late_tag, late_tag, late_tag, late_tag, late_tag,
late_tag, late_tag, late_tag, late_tag, late_tag, late_tag,
late_tag, late_tag, late_tag, late_tag, late_tag, late_tag,
late_tag, late_tag),
std::free);
)";
const auto& lib = Library::Handle(LoadTestScript(script_chars.get()));
const auto& lib = Library::Handle(LoadTestScript(script_chars));
const auto& pragma_can_be_smi =
String::Handle(Symbols::New(thread, "vm-test:can-be-smi"));

View file

@ -1077,8 +1077,7 @@ BoolPtr CallSpecializer::InstanceOfAsBool(
AbstractType::Handle(type.UnwrapFutureOr());
ASSERT(unwrapped_type.IsInstantiated());
is_subtype = unwrapped_type.IsTopTypeForInstanceOf() ||
unwrapped_type.IsNullable() ||
(unwrapped_type.IsLegacy() && unwrapped_type.IsNeverType());
unwrapped_type.IsNullable();
} else {
is_subtype =
Class::IsSubtypeOf(cls, Object::null_type_arguments(),
@ -1167,17 +1166,14 @@ bool CallSpecializer::TryOptimizeInstanceOfUsingStaticTypes(
return false;
}
// If type is Null or Never*, or the static type of the receiver is a
// If type is Null or the static type of the receiver is a
// subtype of the tested type, replace 'receiver is type' with
// - 'receiver == null' if type is Null or Never*,
// - 'receiver == null' if type is Null,
// - 'receiver != null' otherwise.
if (type.IsNullType() || (type.IsNeverType() && type.IsLegacy()) ||
left_value->Type()->IsSubtypeOf(type)) {
if (type.IsNullType() || left_value->Type()->IsSubtypeOf(type)) {
Definition* replacement = new (Z) StrictCompareInstr(
call->source(),
(type.IsNullType() || (type.IsNeverType() && type.IsLegacy()))
? Token::kEQ_STRICT
: Token::kNE_STRICT,
type.IsNullType() ? Token::kEQ_STRICT : Token::kNE_STRICT,
left_value->CopyWithType(Z),
new (Z) Value(flow_graph()->constant_null()),
/* number_check = */ false, DeoptId::kNone);

View file

@ -1020,8 +1020,6 @@ const uint8_t Nullability::kNullable =
static_cast<uint8_t>(dart::Nullability::kNullable);
const uint8_t Nullability::kNonNullable =
static_cast<uint8_t>(dart::Nullability::kNonNullable);
const uint8_t Nullability::kLegacy =
static_cast<uint8_t>(dart::Nullability::kLegacy);
bool Heap::IsAllocatableInNewSpace(intptr_t instance_size) {
return dart::IsAllocatableInNewSpace(instance_size);

View file

@ -761,7 +761,6 @@ class Nullability : public AllStatic {
public:
static const uint8_t kNullable;
static const uint8_t kNonNullable;
static const uint8_t kLegacy;
};
class Double : public AllStatic {

File diff suppressed because it is too large Load diff

View file

@ -601,13 +601,6 @@ static void BuildInstantiateTypeParameterStub(Assembler* assembler,
__ BranchIf(NOT_EQUAL, &runtime_call);
__ Ret();
break;
case Nullability::kLegacy:
__ CompareAbstractTypeNullabilityWith(
InstantiateTypeABI::kResultTypeReg,
static_cast<int8_t>(Nullability::kNonNullable),
InstantiateTypeABI::kScratchReg);
__ BranchIf(EQUAL, &runtime_call);
__ Ret();
}
// The TAV was null, so the value of the type parameter is "dynamic".
@ -630,11 +623,6 @@ void StubCodeCompiler::GenerateInstantiateTypeNullableClassTypeParameterStub() {
/*is_function_parameter=*/false);
}
void StubCodeCompiler::GenerateInstantiateTypeLegacyClassTypeParameterStub() {
BuildInstantiateTypeParameterStub(assembler, Nullability::kLegacy,
/*is_function_parameter=*/false);
}
void StubCodeCompiler::
GenerateInstantiateTypeNonNullableFunctionTypeParameterStub() {
BuildInstantiateTypeParameterStub(assembler, Nullability::kNonNullable,
@ -647,12 +635,6 @@ void StubCodeCompiler::
/*is_function_parameter=*/true);
}
void StubCodeCompiler::
GenerateInstantiateTypeLegacyFunctionTypeParameterStub() {
BuildInstantiateTypeParameterStub(assembler, Nullability::kLegacy,
/*is_function_parameter=*/true);
}
void StubCodeCompiler::GenerateInstantiateTypeStub() {
BuildInstantiateTypeRuntimeCall(assembler);
}

View file

@ -14,31 +14,28 @@ DEBUG_ONLY(DECLARE_FLAG(bool, trace_write_barrier_elimination);)
ISOLATE_UNIT_TEST_CASE(IRTest_WriteBarrierElimination_JoinSuccessors) {
DEBUG_ONLY(
SetFlagScope<bool> sfs(&FLAG_trace_write_barrier_elimination, true));
const char* nullable_tag = TestCase::NullableTag();
const char* null_assert_tag = TestCase::NullAssertTag();
// This is a regression test for a bug where we were using
// JoinEntry::SuccessorCount() to determine the number of outgoing blocks
// from the join block. JoinEntry::SuccessorCount() is in fact always 0;
// JoinEntry::last_instruction()->SuccessorCount() should be used instead.
// clang-format off
auto kScript = Utils::CStringUniquePtr(
OS::SCreate(nullptr, R"(
const char* kScript = R"(
class C {
int%s value;
C%s next;
C%s prev;
int? value;
C? next;
C? prev;
}
@pragma("vm:never-inline")
fn() {}
foo(int x) {
C%s prev = C();
C%s next;
C? prev = C();
C? next;
while (x --> 0) {
next = C();
next%s.prev = prev;
next!.prev = prev;
prev?.next = next;
prev = next;
fn();
@ -47,12 +44,10 @@ ISOLATE_UNIT_TEST_CASE(IRTest_WriteBarrierElimination_JoinSuccessors) {
}
main() { foo(10); }
)",
nullable_tag, nullable_tag, nullable_tag, nullable_tag,
nullable_tag, null_assert_tag), std::free);
)";
// clang-format on
const auto& root_library = Library::Handle(LoadTestScript(kScript.get()));
const auto& root_library = Library::Handle(LoadTestScript(kScript));
Invoke(root_library, "main");
@ -90,10 +85,9 @@ ISOLATE_UNIT_TEST_CASE(IRTest_WriteBarrierElimination_AtLeastOnce) {
// each block at least once, the store "c.next = n" will be marked
// NoWriteBarrier.
// clang-format off
auto kScript = Utils::CStringUniquePtr(OS::SCreate(nullptr,
R"(
const char* kScript = R"(
class C {
%s C next;
late C next;
}
@pragma("vm:never-inline")
@ -110,9 +104,9 @@ ISOLATE_UNIT_TEST_CASE(IRTest_WriteBarrierElimination_AtLeastOnce) {
}
main() { foo(0); foo(10); }
)", TestCase::LateTag()), std::free);
)";
// clang-format on
const auto& root_library = Library::Handle(LoadTestScript(kScript.get()));
const auto& root_library = Library::Handle(LoadTestScript(kScript));
Invoke(root_library, "main");
@ -141,7 +135,6 @@ ISOLATE_UNIT_TEST_CASE(IRTest_WriteBarrierElimination_AtLeastOnce) {
static void TestWBEForArrays(int length) {
DEBUG_ONLY(
SetFlagScope<bool> sfs(&FLAG_trace_write_barrier_elimination, true));
const char* nullable_tag = TestCase::NullableTag();
// Test that array allocations are considered usable after a
// may-trigger-GC instruction (in this case CheckStackOverflow) iff they
@ -150,7 +143,7 @@ static void TestWBEForArrays(int length) {
auto kScript =
Utils::CStringUniquePtr(OS::SCreate(nullptr, R"(
class C {
%s C next;
late C next;
}
@pragma("vm:never-inline")
@ -159,7 +152,7 @@ static void TestWBEForArrays(int length) {
foo(int x) {
C c = C();
C n = C();
List<C%s> array = List<C%s>.filled(%d, null);
List<C?> array = List<C?>.filled(%d, null);
array[0] = c;
while (x --> 0) {
c.next = n;
@ -171,7 +164,7 @@ static void TestWBEForArrays(int length) {
}
main() { foo(10); }
)", TestCase::LateTag(), nullable_tag, nullable_tag, length), std::free);
)", length), std::free);
// clang-format on
// Generate a length dependent test library uri.

View file

@ -3048,46 +3048,15 @@ DART_EXPORT Dart_Handle Dart_StringGetProperties(Dart_Handle object,
// --- Lists ---
DART_EXPORT Dart_Handle Dart_NewList(intptr_t length) {
return Dart_NewListOf(Dart_CoreType_Dynamic, length);
}
static TypeArgumentsPtr TypeArgumentsForElementType(
ObjectStore* store,
Dart_CoreType_Id element_type_id) {
switch (element_type_id) {
case Dart_CoreType_Dynamic:
return TypeArguments::null();
case Dart_CoreType_Int:
return store->type_argument_legacy_int();
case Dart_CoreType_String:
return store->type_argument_legacy_string();
}
UNREACHABLE();
return TypeArguments::null();
}
DART_EXPORT Dart_Handle Dart_NewListOf(Dart_CoreType_Id element_type_id,
intptr_t length) {
DARTSCOPE(Thread::Current());
if (element_type_id != Dart_CoreType_Dynamic) {
return Api::NewError(
"Cannot use legacy types with --sound-null-safety enabled. "
"Use Dart_NewListOfType or Dart_NewListOfTypeFilled instead.");
}
CHECK_LENGTH(length, Array::kMaxElements);
CHECK_CALLBACK_STATE(T);
const Array& arr = Array::Handle(Z, Array::New(length));
if (element_type_id != Dart_CoreType_Dynamic) {
arr.SetTypeArguments(TypeArguments::Handle(
Z, TypeArgumentsForElementType(T->isolate_group()->object_store(),
element_type_id)));
}
return Api::NewHandle(T, arr.ptr());
}
static bool CanTypeContainNull(const Type& type) {
return (type.nullability() == Nullability::kLegacy) ||
(type.nullability() == Nullability::kNullable);
return (type.nullability() == Nullability::kNullable);
}
DART_EXPORT Dart_Handle Dart_NewListOfType(Dart_Handle element_type,
@ -5664,10 +5633,6 @@ DART_EXPORT Dart_Handle Dart_IsNonNullableType(Dart_Handle type, bool* result) {
return IsOfTypeNullabilityHelper(type, Nullability::kNonNullable, result);
}
DART_EXPORT Dart_Handle Dart_IsLegacyType(Dart_Handle type, bool* result) {
return IsOfTypeNullabilityHelper(type, Nullability::kLegacy, result);
}
DART_EXPORT Dart_Handle Dart_LibraryUrl(Dart_Handle library) {
DARTSCOPE(Thread::Current());
const Library& lib = Api::UnwrapLibraryHandle(Z, library);

View file

@ -5030,9 +5030,7 @@ TEST_CASE(DartAPI_TypeGetParameterizedTypes) {
EXPECT_VALID(double_type);
EXPECT_VALID(Dart_ListSetAt(type_args, 1, double_type));
Dart_Handle myclass0_type =
TestCase::IsNNBD()
? Dart_GetNonNullableType(lib, NewString("MyClass0"), 2, &type_args)
: Dart_GetType(lib, NewString("MyClass0"), 2, &type_args);
Dart_GetNonNullableType(lib, NewString("MyClass0"), 2, &type_args);
EXPECT_VALID(myclass0_type);
type_args = Dart_NewList(2);
@ -5045,9 +5043,7 @@ TEST_CASE(DartAPI_TypeGetParameterizedTypes) {
EXPECT_VALID(list_type);
EXPECT_VALID(Dart_ListSetAt(type_args, 1, list_type));
Dart_Handle myclass1_type =
TestCase::IsNNBD()
? Dart_GetNonNullableType(lib, NewString("MyClass1"), 2, &type_args)
: Dart_GetType(lib, NewString("MyClass1"), 2, &type_args);
Dart_GetNonNullableType(lib, NewString("MyClass1"), 2, &type_args);
EXPECT_VALID(myclass1_type);
// Now create objects of the type and validate the object type matches
@ -5427,8 +5423,7 @@ TEST_CASE(DartAPI_SetField_FunnyValue) {
}
TEST_CASE(DartAPI_SetField_BadType) {
const char* kScriptChars =
TestCase::IsNNBD() ? "late int foo;\n" : "int foo;\n";
const char* kScriptChars = "late int foo;\n";
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
Dart_Handle name = NewString("foo");
Dart_Handle result = Dart_SetField(lib, name, Dart_True());
@ -5451,26 +5446,24 @@ static Dart_NativeFunction native_field_lookup(Dart_Handle name,
TEST_CASE(DartAPI_InjectNativeFields2) {
// clang-format off
auto kScriptChars = Utils::CStringUniquePtr(
OS::SCreate(nullptr,
const char* kScriptChars =
"class NativeFields extends NativeFieldsWrapper {\n"
" NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
" int fld1;\n"
" final int fld;\n"
" static int%s fld3;\n"
" static int? fld3;\n"
" static const int fld4 = 10;\n"
"}\n"
"NativeFields testMain() {\n"
" NativeFields obj = new NativeFields(10, 20);\n"
" return obj;\n"
"}\n",
TestCase::NullableTag()), std::free);
"}\n";
// clang-format on
Dart_Handle result;
// Create a test library and Load up a test script in it.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars.get(), nullptr,
USER_TEST_URI, false);
Dart_Handle lib =
TestCase::LoadTestScript(kScriptChars, nullptr, USER_TEST_URI, false);
// Invoke a function which returns an object of type NativeFields.
result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
@ -5483,29 +5476,26 @@ TEST_CASE(DartAPI_InjectNativeFields2) {
TEST_CASE(DartAPI_InjectNativeFields3) {
// clang-format off
auto kScriptChars = Utils::CStringUniquePtr(
OS::SCreate(nullptr,
const char* kScriptChars =
"import 'dart:nativewrappers';"
"final class NativeFields "
"extends NativeFieldWrapperClass2 {\n"
" NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
" int fld1;\n"
" final int fld2;\n"
" static int%s fld3;\n"
" static int? fld3;\n"
" static const int fld4 = 10;\n"
"}\n"
"NativeFields testMain() {\n"
" NativeFields obj = new NativeFields(10, 20);\n"
" return obj;\n"
"}\n",
TestCase::NullableTag()), std::free);
"}\n";
// clang-format on
Dart_Handle result;
const int kNumNativeFields = 2;
// Load up a test script in the test library.
Dart_Handle lib =
TestCase::LoadTestScript(kScriptChars.get(), native_field_lookup);
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, native_field_lookup);
// Invoke a function which returns an object of type NativeFields.
result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
@ -5531,24 +5521,22 @@ TEST_CASE(DartAPI_InjectNativeFields3) {
TEST_CASE(DartAPI_InjectNativeFields4) {
// clang-format off
auto kScriptChars = Utils::CStringUniquePtr(
OS::SCreate(nullptr,
const char* kScriptChars =
"class NativeFields extends NativeFieldsWrapperClass2 {\n"
" NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
" int fld1;\n"
" final int fld;\n"
" static int%s fld3;\n"
" static int? fld3;\n"
" static const int fld4 = 10;\n"
"}\n"
"NativeFields testMain() {\n"
" NativeFields obj = new NativeFields(10, 20);\n"
" return obj;\n"
"}\n",
TestCase::NullableTag()), std::free);
"}\n";
// clang-format on
Dart_Handle result;
// Load up a test script in the test library.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars.get(), nullptr);
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
// Invoke a function which returns an object of type NativeFields.
result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
@ -5625,22 +5613,19 @@ static Dart_NativeFunction TestNativeFieldsAccess_lookup(Dart_Handle name,
}
TEST_CASE(DartAPI_TestNativeFieldsAccess) {
const char* nullable_tag = TestCase::NullableTag();
// clang-format off
auto kScriptChars = Utils::CStringUniquePtr(
OS::SCreate(
nullptr, R"(
const char* kScriptChars = R"(
import 'dart:nativewrappers';
base class NativeFields extends NativeFieldWrapperClass2 {
NativeFields(int i, int j) : fld1 = i, fld2 = j {}
int fld1;
final int fld2;
static int%s fld3;
static int? fld3;
static const int fld4 = 10;
@pragma('vm:external-name', 'TestNativeFieldsAccess_init')
external int%s initNativeFlds();
external int? initNativeFlds();
@pragma('vm:external-name', 'TestNativeFieldsAccess_access')
external int%s accessNativeFlds(int%s i);
external int? accessNativeFlds(int? i);
}
class NoNativeFields {
int neitherATypedDataNorNull = 0;
@ -5654,14 +5639,12 @@ TEST_CASE(DartAPI_TestNativeFieldsAccess) {
new NoNativeFields().invalidAccess();
return obj;
}
)",
nullable_tag, nullable_tag, nullable_tag, nullable_tag),
std::free);
)";
// clang-format on
// Load up a test script in the test library.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars.get(),
TestNativeFieldsAccess_lookup);
Dart_Handle lib =
TestCase::LoadTestScript(kScriptChars, TestNativeFieldsAccess_lookup);
// Invoke a function which returns an object of type NativeFields.
Dart_Handle result = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
@ -5773,30 +5756,25 @@ static void TestNativeFields(Dart_Handle retobj) {
}
TEST_CASE(DartAPI_ImplicitNativeFieldAccess) {
const char* nullable_tag = TestCase::NullableTag();
// clang-format off
auto kScriptChars = Utils::CStringUniquePtr(
OS::SCreate(nullptr,
const char* kScriptChars =
"import 'dart:nativewrappers';"
"final class NativeFields extends "
"NativeFieldWrapperClass4 {\n"
" NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
" int%s fld0;\n"
" int? fld0;\n"
" int fld1;\n"
" final int fld2;\n"
" static int%s fld3;\n"
" static int? fld3;\n"
" static const int fld4 = 10;\n"
"}\n"
"NativeFields testMain() {\n"
" NativeFields obj = new NativeFields(10, 20);\n"
" return obj;\n"
"}\n",
nullable_tag, nullable_tag),
std::free);
"}\n";
// clang-format on
// Load up a test script in the test library.
Dart_Handle lib =
TestCase::LoadTestScript(kScriptChars.get(), native_field_lookup);
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, native_field_lookup);
// Invoke a function which returns an object of type NativeFields.
Dart_Handle retobj = Dart_Invoke(lib, NewString("testMain"), 0, nullptr);
@ -5808,14 +5786,13 @@ TEST_CASE(DartAPI_ImplicitNativeFieldAccess) {
TEST_CASE(DartAPI_NegativeNativeFieldAccess) {
// clang-format off
auto kScriptChars = Utils::CStringUniquePtr(
OS::SCreate(nullptr,
const char* kScriptChars =
"import 'dart:nativewrappers';\n"
"class NativeFields {\n"
" NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
" int fld1;\n"
" final int fld2;\n"
" static int%s fld3;\n"
" static int? fld3;\n"
" static const int fld4 = 10;\n"
"}\n"
"NativeFields testMain1() {\n"
@ -5824,16 +5801,14 @@ TEST_CASE(DartAPI_NegativeNativeFieldAccess) {
"}\n"
"Function testMain2() {\n"
" return () {};\n"
"}\n",
TestCase::NullableTag()),
std::free);
"}\n";
// clang-format on
Dart_Handle result;
CHECK_API_SCOPE(thread);
// Create a test library and Load up a test script in it.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars.get(), nullptr);
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
// Invoke a function which returns an object of type NativeFields.
Dart_Handle retobj = Dart_Invoke(lib, NewString("testMain1"), 0, nullptr);
@ -6385,54 +6360,6 @@ TEST_CASE(DartAPI_InvokeClosure_Issue44205) {
EXPECT_ERROR(result, "String' is not a subtype of type 'int' of 'j'");
}
TEST_CASE(DartAPI_NewListOf) {
const char* kScriptChars =
"String expectListOfString(List<String> o) => '${o.first}';\n"
"String expectListOfDynamic(List<dynamic> o) => '${o.first}';\n"
"String expectListOfInt(List<int> o) => '${o.first}';\n";
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, nullptr);
const int kNumArgs = 1;
Dart_Handle args[kNumArgs];
const char* str;
Dart_Handle result;
Dart_Handle string_list = Dart_NewListOf(Dart_CoreType_String, 1);
if (!Dart_IsError(string_list)) {
args[0] = string_list;
Dart_Handle result =
Dart_Invoke(lib, NewString("expectListOfString"), kNumArgs, args);
EXPECT_VALID(result);
result = Dart_StringToCString(result, &str);
EXPECT_VALID(result);
EXPECT_STREQ("null", str);
} else {
EXPECT_ERROR(string_list,
"Cannot use legacy types with --sound-null-safety enabled. "
"Use Dart_NewListOfType or Dart_NewListOfTypeFilled instead.");
}
Dart_Handle dynamic_list = Dart_NewListOf(Dart_CoreType_Dynamic, 1);
EXPECT_VALID(dynamic_list);
args[0] = dynamic_list;
result = Dart_Invoke(lib, NewString("expectListOfDynamic"), kNumArgs, args);
EXPECT_VALID(result);
result = Dart_StringToCString(result, &str);
EXPECT_STREQ("null", str);
Dart_Handle int_list = Dart_NewListOf(Dart_CoreType_Int, 1);
if (!Dart_IsError(int_list)) {
args[0] = int_list;
result = Dart_Invoke(lib, NewString("expectListOfInt"), kNumArgs, args);
EXPECT_VALID(result);
result = Dart_StringToCString(result, &str);
EXPECT_STREQ("null", str);
} else {
EXPECT_ERROR(int_list,
"Cannot use legacy types with --sound-null-safety enabled. "
"Use Dart_NewListOfType or Dart_NewListOfTypeFilled instead.");
}
}
TEST_CASE(DartAPI_NewListOfType) {
const char* kScriptChars =
"class ZXHandle {}\n"
@ -7304,41 +7231,14 @@ TEST_CASE(DartAPI_TypeToNullability) {
const Dart_Handle name = NewString("Class");
// Lookup the legacy type for Class.
Dart_Handle type = Dart_GetType(lib, name, 0, nullptr);
Dart_Handle nonNullableType;
Dart_Handle nullableType;
if (Dart_IsError(type)) {
EXPECT_ERROR(
type,
"Cannot use legacy types with --sound-null-safety enabled. "
"Use Dart_GetNullableType or Dart_GetNonNullableType instead.");
EXPECT_ERROR(type,
"Cannot use legacy types with --sound-null-safety enabled. "
"Use Dart_GetNullableType or Dart_GetNonNullableType instead.");
nonNullableType = Dart_GetNonNullableType(lib, name, 0, nullptr);
EXPECT_VALID(nonNullableType);
nullableType = Dart_GetNullableType(lib, name, 0, nullptr);
} else {
EXPECT_VALID(type);
bool result = false;
EXPECT_VALID(Dart_IsLegacyType(type, &result));
EXPECT(result);
// Legacy -> Nullable
nullableType = Dart_TypeToNullableType(type);
EXPECT_VALID(nullableType);
result = false;
EXPECT_VALID(Dart_IsNullableType(nullableType, &result));
EXPECT(result);
EXPECT(Dart_IdentityEquals(nullableType,
Dart_GetNullableType(lib, name, 0, nullptr)));
// Legacy -> Non-Nullable
nonNullableType = Dart_TypeToNonNullableType(type);
EXPECT_VALID(nonNullableType);
result = false;
EXPECT_VALID(Dart_IsNonNullableType(nonNullableType, &result));
EXPECT(result);
EXPECT(Dart_IdentityEquals(nonNullableType,
Dart_GetNonNullableType(lib, name, 0, nullptr)));
}
Dart_Handle nonNullableType = Dart_GetNonNullableType(lib, name, 0, nullptr);
EXPECT_VALID(nonNullableType);
Dart_Handle nullableType = Dart_GetNullableType(lib, name, 0, nullptr);
EXPECT_VALID(nullableType);
// Nullable -> Non-Nullable
EXPECT(Dart_IdentityEquals(

File diff suppressed because it is too large Load diff

View file

@ -434,12 +434,11 @@ class Reader : public ValueObject {
switch (kernel_nullability) {
case KernelNullability::kNullable:
return Nullability::kNullable;
case KernelNullability::kLegacy:
FATAL("Legacy nullability is not supported.");
return Nullability::kLegacy;
case KernelNullability::kNonNullable:
case KernelNullability::kUndetermined:
return Nullability::kNonNullable;
case KernelNullability::kLegacy:
FATAL("Legacy nullability is not supported.");
}
UNREACHABLE();
}

View file

@ -1949,9 +1949,6 @@ ErrorPtr Object::Init(IsolateGroup* isolate_group,
type = Type::NewNonParameterizedType(cls);
ASSERT(type.IsCanonical());
object_store->set_object_type(type);
type = type.ToNullability(Nullability::kLegacy, Heap::kOld);
ASSERT(type.IsCanonical());
object_store->set_legacy_object_type(type);
type = type.ToNullability(Nullability::kNonNullable, Heap::kOld);
ASSERT(type.IsCanonical());
object_store->set_non_nullable_object_type(type);
@ -2292,8 +2289,6 @@ ErrorPtr Object::Init(IsolateGroup* isolate_group,
pending_classes.Add(cls);
type = Type::NewNonParameterizedType(cls);
object_store->set_int_type(type);
type = type.ToNullability(Nullability::kLegacy, Heap::kOld);
object_store->set_legacy_int_type(type);
type = type.ToNullability(Nullability::kNonNullable, Heap::kOld);
object_store->set_non_nullable_int_type(type);
type = type.ToNullability(Nullability::kNullable, Heap::kOld);
@ -2321,8 +2316,6 @@ ErrorPtr Object::Init(IsolateGroup* isolate_group,
pending_classes.Add(cls);
type = Type::NewNonParameterizedType(cls);
object_store->set_string_type(type);
type = type.ToNullability(Nullability::kLegacy, Heap::kOld);
object_store->set_legacy_string_type(type);
cls = object_store->bool_class();
type = Type::NewNonParameterizedType(cls);
@ -2331,7 +2324,6 @@ ErrorPtr Object::Init(IsolateGroup* isolate_group,
cls = object_store->smi_class();
type = Type::NewNonParameterizedType(cls);
object_store->set_smi_type(type);
type = type.ToNullability(Nullability::kLegacy, Heap::kOld);
cls = object_store->mint_class();
type = Type::NewNonParameterizedType(cls);
@ -2374,11 +2366,6 @@ ErrorPtr Object::Init(IsolateGroup* isolate_group,
type_args.SetTypeAt(0, type);
type_args = type_args.Canonicalize(thread);
object_store->set_type_argument_int(type_args);
type_args = TypeArguments::New(1);
type = object_store->legacy_int_type();
type_args.SetTypeAt(0, type);
type_args = type_args.Canonicalize(thread);
object_store->set_type_argument_legacy_int(type_args);
type_args = TypeArguments::New(1);
type = object_store->double_type();
@ -2391,11 +2378,6 @@ ErrorPtr Object::Init(IsolateGroup* isolate_group,
type_args.SetTypeAt(0, type);
type_args = type_args.Canonicalize(thread);
object_store->set_type_argument_string(type_args);
type_args = TypeArguments::New(1);
type = object_store->legacy_string_type();
type_args.SetTypeAt(0, type);
type_args = type_args.Canonicalize(thread);
object_store->set_type_argument_legacy_string(type_args);
type_args = TypeArguments::New(2);
type = object_store->string_type();
@ -6810,13 +6792,10 @@ intptr_t TypeArguments::ComputeNullability() const {
if (!type.IsNull()) {
switch (type.nullability()) {
case Nullability::kNullable:
type_bits = kNullableBits;
type_bits = kNullableBit;
break;
case Nullability::kNonNullable:
type_bits = kNonNullableBits;
break;
case Nullability::kLegacy:
type_bits = kLegacyBits;
type_bits = kNonNullableBit;
break;
default:
UNREACHABLE();
@ -7423,10 +7402,10 @@ bool TypeArguments::IsUninstantiatedIdentity() const {
if ((type_param.index() != i) || type_param.IsFunctionTypeParameter()) {
return false;
}
// Instantiating nullable and legacy type parameters may change
// Instantiating nullable type parameters may change
// nullability of a type, so type arguments vector containing such type
// parameters cannot be substituted with instantiator type arguments.
if (type_param.IsNullable() || type_param.IsLegacy()) {
if (type_param.IsNullable()) {
return false;
}
}
@ -7483,14 +7462,14 @@ bool TypeArguments::CanShareInstantiatorTypeArguments(
if ((type_param.index() != i) || type_param.IsFunctionTypeParameter()) {
return false;
}
// Instantiating nullable and legacy type parameters may change nullability
// Instantiating nullable type parameters may change nullability
// of a type, so type arguments vector containing such type parameters
// cannot be substituted with instantiator type arguments, unless we check
// at runtime the nullability of the first 1 or 2 type arguments of the
// instantiator.
// Note that the presence of non-overlapping super type arguments (i.e.
// first_type_param_offset > 0) will prevent this optimization.
if (type_param.IsNullable() || type_param.IsLegacy()) {
if (type_param.IsNullable()) {
if (with_runtime_check == nullptr || i >= kNullabilityMaxTypes) {
return false;
}
@ -7554,12 +7533,12 @@ bool TypeArguments::CanShareFunctionTypeArguments(
if ((type_param.index() != i) || !type_param.IsFunctionTypeParameter()) {
return false;
}
// Instantiating nullable and legacy type parameters may change nullability
// Instantiating nullable type parameters may change nullability
// of a type, so type arguments vector containing such type parameters
// cannot be substituted with the enclosing function type arguments, unless
// we check at runtime the nullability of the first 1 or 2 type arguments of
// the enclosing function type arguments.
if (type_param.IsNullable() || type_param.IsLegacy()) {
if (type_param.IsNullable()) {
if (with_runtime_check == nullptr || i >= kNullabilityMaxTypes) {
return false;
}
@ -20707,16 +20686,16 @@ bool Instance::NullIsInstanceOf(
return Instance::NullIsInstanceOf(type, Object::null_type_arguments(),
Object::null_type_arguments());
}
return other.IsLegacy() && (other.IsObjectType() || other.IsNeverType());
return false;
}
// Must be kept in sync with GenerateNullIsAssignableToType in
// stub_code_compiler.cc if any changes are made.
bool Instance::NullIsAssignableTo(const AbstractType& other) {
// "Left Null" rule: null is assignable when destination type is either
// legacy or nullable. Otherwise it is not assignable or we cannot tell
// "Left Null" rule: null is assignable when destination type is
// nullable. Otherwise it is not assignable or we cannot tell
// without instantiating type parameter.
if (other.IsLegacy() || other.IsNullable()) {
if (other.IsNullable()) {
return true;
}
if (other.IsFutureOrType()) {
@ -21126,16 +21105,11 @@ AbstractTypePtr AbstractType::SetInstantiatedNullability(
const Nullability arg_nullability = nullability();
const Nullability var_nullability = type_param.nullability();
// Adjust nullability of result 'arg' instantiated from 'var'.
// arg/var ! ? *
// ! ! ? *
// ? ? ? ?
// * * ? *
if (var_nullability == Nullability::kNullable ||
arg_nullability == Nullability::kNullable) {
// arg/var ! ?
// ! ! ?
// ? ? ?
if (var_nullability == Nullability::kNullable) {
result_nullability = Nullability::kNullable;
} else if (var_nullability == Nullability::kLegacy ||
arg_nullability == Nullability::kLegacy) {
result_nullability = Nullability::kLegacy;
} else {
// Keep arg nullability.
return ptr();
@ -21171,12 +21145,9 @@ AbstractTypePtr AbstractType::NormalizeFutureOrType(Heap::Space space) const {
if (IsNonNullable()) {
return unwrapped_type.ptr();
}
if (IsNullable() || unwrapped_type.IsNullable()) {
return Type::Cast(unwrapped_type)
.ToNullability(Nullability::kNullable, space);
}
ASSERT(IsNullable());
return Type::Cast(unwrapped_type)
.ToNullability(Nullability::kLegacy, space);
.ToNullability(Nullability::kNullable, space);
}
if (cid == kNeverCid && unwrapped_type.IsNonNullable()) {
ObjectStore* object_store = IsolateGroup::Current()->object_store();
@ -21226,7 +21197,7 @@ void AbstractType::set_type_state(UntaggedAbstractType::TypeState value) const {
void AbstractType::set_nullability(Nullability value) const {
ASSERT(!IsCanonical());
set_flags(UntaggedAbstractType::NullabilityBits::update(
set_flags(UntaggedAbstractType::NullabilityBit::update(
static_cast<uint8_t>(value), untag()->flags()));
}
@ -21253,16 +21224,8 @@ bool AbstractType::IsNullabilityEquivalent(Thread* thread,
return false;
}
} else {
if (kind == TypeEquality::kSyntactical) {
if (this_type_nullability == Nullability::kLegacy) {
this_type_nullability = Nullability::kNonNullable;
}
if (other_type_nullability == Nullability::kLegacy) {
other_type_nullability = Nullability::kNonNullable;
}
} else {
ASSERT(kind == TypeEquality::kCanonical);
}
ASSERT((kind == TypeEquality::kSyntactical) ||
(kind == TypeEquality::kCanonical));
if (this_type_nullability != other_type_nullability) {
return false;
}
@ -21369,10 +21332,6 @@ const char* AbstractType::NullabilitySuffix(
return "?";
case Nullability::kNonNullable:
return "";
case Nullability::kLegacy:
return (FLAG_show_internal_names || name_visibility != kUserVisibleName)
? "*"
: "";
default:
UNREACHABLE();
}
@ -21443,7 +21402,7 @@ bool AbstractType::IsTopTypeForInstanceOf() const {
return true;
}
if (cid == kInstanceCid) { // Object type.
return !IsNonNullable(); // kLegacy or kNullable.
return IsNullable();
}
if (cid == kFutureOrCid) {
// FutureOr<T> where T is a top type behaves as a top type.
@ -22400,13 +22359,7 @@ void Type::PrintName(NameVisibility name_visibility,
uword Type::ComputeHash() const {
ASSERT(IsFinalized());
uint32_t result = type_class_id();
// A legacy type should have the same hash as its non-nullable version to be
// consistent with the definition of type equality in Dart code.
Nullability type_nullability = nullability();
if (type_nullability == Nullability::kLegacy) {
type_nullability = Nullability::kNonNullable;
}
result = CombineHashes(result, static_cast<uint32_t>(type_nullability));
result = CombineHashes(result, static_cast<uint32_t>(nullability()));
uint32_t type_args_hash = TypeArguments::kAllDynamicHash;
if (arguments() != TypeArguments::null()) {
const TypeArguments& args = TypeArguments::Handle(arguments());
@ -22422,13 +22375,7 @@ uword FunctionType::ComputeHash() const {
ASSERT(IsFinalized());
uint32_t result =
CombineHashes(packed_parameter_counts(), packed_type_parameter_counts());
// A legacy type should have the same hash as its non-nullable version to be
// consistent with the definition of type equality in Dart code.
Nullability type_nullability = nullability();
if (type_nullability == Nullability::kLegacy) {
type_nullability = Nullability::kNonNullable;
}
result = CombineHashes(result, static_cast<uint32_t>(type_nullability));
result = CombineHashes(result, static_cast<uint32_t>(nullability()));
AbstractType& type = AbstractType::Handle();
const intptr_t num_type_params = NumTypeParameters();
if (num_type_params > 0) {
@ -22978,13 +22925,7 @@ uword TypeParameter::ComputeHash() const {
uint32_t result = parameterized_class_id();
result = CombineHashes(result, base());
result = CombineHashes(result, index());
// A legacy type should have the same hash as its non-nullable version to be
// consistent with the definition of type equality in Dart code.
Nullability type_param_nullability = nullability();
if (type_param_nullability == Nullability::kLegacy) {
type_param_nullability = Nullability::kNonNullable;
}
result = CombineHashes(result, static_cast<uint32_t>(type_param_nullability));
result = CombineHashes(result, static_cast<uint32_t>(nullability()));
result = FinalizeHash(result, kHashBits);
SetHash(result);
return result;
@ -27617,13 +27558,7 @@ bool RecordType::IsEquivalent(
uword RecordType::ComputeHash() const {
ASSERT(IsFinalized());
uint32_t result = 0;
// A legacy type should have the same hash as its non-nullable version to be
// consistent with the definition of type equality in Dart code.
Nullability type_nullability = nullability();
if (type_nullability == Nullability::kLegacy) {
type_nullability = Nullability::kNonNullable;
}
result = CombineHashes(result, static_cast<uint32_t>(type_nullability));
result = CombineHashes(result, static_cast<uint32_t>(nullability()));
result = CombineHashes(result, static_cast<uint32_t>(shape().AsInt()));
AbstractType& type = AbstractType::Handle();
const intptr_t num_fields = NumFields();

View file

@ -1112,8 +1112,6 @@ typedef ZoneGrowableHandlePtrArray<const String> URIs;
enum class Nullability : uint8_t {
kNullable = 0,
kNonNullable = 1,
kLegacy = 2,
// Adjust kNullabilityBitSize in app_snapshot.cc if adding new values.
};
// Equality kind between types.
@ -8580,21 +8578,18 @@ class TypeArguments : public Instance {
// of performing a more costly instantiation of the uninstantiated type
// arguments (UTA).
// The vector nullability is stored as a bit vector (in a Smi field), using
// 2 bits per type:
// - the high bit is set if the type is nullable or legacy.
// - the low bit is set if the type is nullable.
// 1 bit per type, which is set if the type is nullable.
// The nullability is 0 if the vector is longer than kNullabilityMaxTypes.
// The condition evaluated at runtime to decide whether UTA can share ITA is
// (UTA.nullability & ITA.nullability) == UTA.nullability
// Note that this allows for ITA to be longer than UTA (the bit vector must be
// stored in the same order as the corresponding type vector, i.e. with the
// least significant 2 bits representing the nullability of the first type).
static constexpr intptr_t kNullabilityBitsPerType = 2;
// least significant bit representing the nullability of the first type).
static constexpr intptr_t kNullabilityBitsPerType = 1;
static constexpr intptr_t kNullabilityMaxTypes =
kSmiBits / kNullabilityBitsPerType;
static constexpr intptr_t kNonNullableBits = 0;
static constexpr intptr_t kNullableBits = 3;
static constexpr intptr_t kLegacyBits = 2;
static constexpr intptr_t kNonNullableBit = 0;
static constexpr intptr_t kNullableBit = 1;
intptr_t nullability() const;
static intptr_t nullability_offset() {
return OFFSET_OF(UntaggedTypeArguments, nullability_);
@ -9036,7 +9031,7 @@ class AbstractType : public Instance {
Nullability nullability() const {
return static_cast<Nullability>(
UntaggedAbstractType::NullabilityBits::decode(untag()->flags()));
UntaggedAbstractType::NullabilityBit::decode(untag()->flags()));
}
// Returns true if type has '?' nullability suffix, or it is a
// built-in type which is always nullable (Null, dynamic or void).
@ -9048,9 +9043,6 @@ class AbstractType : public Instance {
bool IsNonNullable() const {
return nullability() == Nullability::kNonNullable;
}
// Returns true if type has '*' nullability suffix, i.e.
// it is from a legacy (opted-out) library.
bool IsLegacy() const { return nullability() == Nullability::kLegacy; }
// Returns true if it is guaranteed that null cannot be
// assigned to this type.
bool IsStrictlyNonNullable() const;
@ -9471,7 +9463,7 @@ class Type : public AbstractType {
static TypePtr New(const Class& clazz,
const TypeArguments& arguments,
Nullability nullability = Nullability::kLegacy,
Nullability nullability = Nullability::kNonNullable,
Heap::Space space = Heap::kOld);
private:
@ -9757,9 +9749,10 @@ class FunctionType : public AbstractType {
return RoundedAllocationSize(sizeof(UntaggedFunctionType));
}
static FunctionTypePtr New(intptr_t num_parent_type_arguments = 0,
Nullability nullability = Nullability::kLegacy,
Heap::Space space = Heap::kOld);
static FunctionTypePtr New(
intptr_t num_parent_type_arguments = 0,
Nullability nullability = Nullability::kNonNullable,
Heap::Space space = Heap::kOld);
static FunctionTypePtr Clone(const FunctionType& orig, Heap::Space space);
@ -11379,7 +11372,7 @@ class RecordType : public AbstractType {
static RecordTypePtr New(RecordShape shape,
const Array& field_types,
Nullability nullability = Nullability::kLegacy,
Nullability nullability = Nullability::kNonNullable,
Heap::Space space = Heap::kOld);
private:

View file

@ -30,10 +30,6 @@ class ObjectPointerVisitor;
M(TypedData, typed_data) \
M(VMService, _vmservice)
// TODO(liama): Once NNBD is enabled, *_type will be deleted and all uses will
// be replaced with *_type_non_nullable. Later, once we drop support for opted
// out code, *_type_legacy will be deleted.
//
// R_ - needs getter only
// RW - needs getter and setter
// ARW_RELAXED - needs getter and setter with relaxed atomic access
@ -71,7 +67,6 @@ class ObjectPointerVisitor;
LAZY_ISOLATE(Function, handle_message_function) \
RW(Class, object_class) \
RW(Type, object_type) \
RW(Type, legacy_object_type) \
RW(Type, non_nullable_object_type) \
RW(Type, nullable_object_type) \
RW(Class, null_class) \
@ -85,7 +80,6 @@ class ObjectPointerVisitor;
RW(Type, number_type) \
RW(Type, nullable_number_type) \
RW(Type, int_type) \
RW(Type, legacy_int_type) \
RW(Type, non_nullable_int_type) \
RW(Type, nullable_int_type) \
RW(Class, integer_implementation_class) \
@ -101,13 +95,10 @@ class ObjectPointerVisitor;
RW(Type, int32x4_type) \
RW(Type, float64x2_type) \
RW(Type, string_type) \
RW(Type, legacy_string_type) \
RW(TypeArguments, type_argument_int) \
RW(TypeArguments, type_argument_legacy_int) \
RW(TypeArguments, type_argument_double) \
RW(TypeArguments, type_argument_never) \
RW(TypeArguments, type_argument_string) \
RW(TypeArguments, type_argument_legacy_string) \
RW(TypeArguments, type_argument_string_dynamic) \
RW(TypeArguments, type_argument_string_string) \
RW(Class, compiletime_error_class) \

View file

@ -5426,8 +5426,7 @@ static void PrintMetadata(const char* name, const Object& data) {
TEST_CASE(Metadata) {
// clang-format off
auto kScriptChars =
Utils::CStringUniquePtr(OS::SCreate(nullptr,
const char* kScriptChars =
"@metafoo \n"
"class Meta { \n"
" final m; \n"
@ -5438,7 +5437,7 @@ TEST_CASE(Metadata) {
"const metabar = 'meta' 'bar'; \n"
" \n"
"@metafoo \n"
"@Meta(0) String%s gVar; \n"
"@Meta(0) String? gVar; \n"
" \n"
"@metafoo \n"
"get tlGetter => gVar; \n"
@ -5457,11 +5456,10 @@ TEST_CASE(Metadata) {
"@Meta('main') \n"
"A main() { \n"
" return A(); \n"
"} \n",
TestCase::NullableTag()), std::free);
"} \n";
// clang-format on
Dart_Handle h_lib = TestCase::LoadTestScript(kScriptChars.get(), nullptr);
Dart_Handle h_lib = TestCase::LoadTestScript(kScriptChars, nullptr);
EXPECT_VALID(h_lib);
Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, nullptr);
EXPECT_VALID(result);
@ -7437,9 +7435,6 @@ ISOLATE_UNIT_TEST_CASE(ClosureType_SubtypeOfFunctionType) {
auto& closure_type_nullable = Type::Handle(
closure_type.ToNullability(Nullability::kNullable, Heap::kNew));
FinalizeAndCanonicalize(&closure_type_nullable);
auto& closure_type_legacy = Type::Handle(
closure_type.ToNullability(Nullability::kLegacy, Heap::kNew));
FinalizeAndCanonicalize(&closure_type_legacy);
auto& closure_type_nonnullable = Type::Handle(
closure_type.ToNullability(Nullability::kNonNullable, Heap::kNew));
FinalizeAndCanonicalize(&closure_type_nonnullable);
@ -7449,21 +7444,13 @@ ISOLATE_UNIT_TEST_CASE(ClosureType_SubtypeOfFunctionType) {
auto& function_type_nullable = Type::Handle(
function_type.ToNullability(Nullability::kNullable, Heap::kNew));
FinalizeAndCanonicalize(&function_type_nullable);
auto& function_type_legacy = Type::Handle(
function_type.ToNullability(Nullability::kLegacy, Heap::kNew));
FinalizeAndCanonicalize(&function_type_legacy);
auto& function_type_nonnullable = Type::Handle(
function_type.ToNullability(Nullability::kNonNullable, Heap::kNew));
FinalizeAndCanonicalize(&function_type_nonnullable);
EXPECT_SUBTYPE(closure_type_nonnullable, function_type_nullable);
EXPECT_SUBTYPE(closure_type_nonnullable, function_type_legacy);
EXPECT_SUBTYPE(closure_type_nonnullable, function_type_nonnullable);
EXPECT_SUBTYPE(closure_type_legacy, function_type_nullable);
EXPECT_SUBTYPE(closure_type_legacy, function_type_legacy);
EXPECT_SUBTYPE(closure_type_legacy, function_type_nonnullable);
EXPECT_SUBTYPE(closure_type_nullable, function_type_nullable);
EXPECT_SUBTYPE(closure_type_nullable, function_type_legacy);
EXPECT_NOT_SUBTYPE(closure_type_nullable, function_type_nonnullable);
const auto& async_lib = Library::Handle(Library::AsyncLibrary());
@ -7472,9 +7459,6 @@ ISOLATE_UNIT_TEST_CASE(ClosureType_SubtypeOfFunctionType) {
auto& tav_function_nullable = TypeArguments::Handle(TypeArguments::New(1));
tav_function_nullable.SetTypeAt(0, function_type_nullable);
tav_function_nullable = tav_function_nullable.Canonicalize(thread);
auto& tav_function_legacy = TypeArguments::Handle(TypeArguments::New(1));
tav_function_legacy.SetTypeAt(0, function_type_legacy);
tav_function_legacy = tav_function_legacy.Canonicalize(thread);
auto& tav_function_nonnullable = TypeArguments::Handle(TypeArguments::New(1));
tav_function_nonnullable.SetTypeAt(0, function_type_nonnullable);
tav_function_nonnullable = tav_function_nonnullable.Canonicalize(thread);
@ -7482,21 +7466,13 @@ ISOLATE_UNIT_TEST_CASE(ClosureType_SubtypeOfFunctionType) {
auto& future_or_function_type_nullable =
Type::Handle(Type::New(future_or_class, tav_function_nullable));
FinalizeAndCanonicalize(&future_or_function_type_nullable);
auto& future_or_function_type_legacy =
Type::Handle(Type::New(future_or_class, tav_function_legacy));
FinalizeAndCanonicalize(&future_or_function_type_legacy);
auto& future_or_function_type_nonnullable =
Type::Handle(Type::New(future_or_class, tav_function_nonnullable));
FinalizeAndCanonicalize(&future_or_function_type_nonnullable);
EXPECT_SUBTYPE(closure_type_nonnullable, future_or_function_type_nullable);
EXPECT_SUBTYPE(closure_type_nonnullable, future_or_function_type_legacy);
EXPECT_SUBTYPE(closure_type_nonnullable, future_or_function_type_nonnullable);
EXPECT_SUBTYPE(closure_type_legacy, future_or_function_type_nullable);
EXPECT_SUBTYPE(closure_type_legacy, future_or_function_type_legacy);
EXPECT_SUBTYPE(closure_type_legacy, future_or_function_type_nonnullable);
EXPECT_SUBTYPE(closure_type_nullable, future_or_function_type_nullable);
EXPECT_SUBTYPE(closure_type_nullable, future_or_function_type_legacy);
EXPECT_NOT_SUBTYPE(closure_type_nullable,
future_or_function_type_nonnullable);
}
@ -7696,16 +7672,6 @@ ISOLATE_UNIT_TEST_CASE(AbstractType_NormalizeFutureOrType) {
EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(type_non_nullable_object, type);
}
// if S is Object* then S
{
const auto& type_legacy_object =
Type::Handle(object_store->legacy_object_type());
const auto& type = AbstractType::Handle(
normalized_future_or(type_legacy_object, Nullability::kNonNullable));
EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(type_legacy_object, type);
}
// if S is Never then Future<Never>
{
@ -7787,8 +7753,6 @@ FutureOr<T?> bar<T>() { return null; }
Type::Handle(object_store->nullable_object_type());
const auto& type_non_nullable_object =
Type::Handle(object_store->non_nullable_object_type());
const auto& type_legacy_object =
Type::Handle(object_store->legacy_object_type());
// Testing same cases as AbstractType_NormalizeFutureOrType.
@ -7840,14 +7804,6 @@ FutureOr<T?> bar<T>() { return null; }
EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(type_nullable_object, got);
}
// FutureOr<T?>[Object*] = Object?
{
const auto& got = AbstractType::Handle(
instantiate_future_or(future_or_nullable_T, type_legacy_object));
EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(type_nullable_object, got);
}
// FutureOr<T>?[Object] = Object?
{
@ -7856,14 +7812,6 @@ FutureOr<T?> bar<T>() { return null; }
EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(type_nullable_object, got);
}
// FutureOr<T>?[Object*] = Object?
{
const auto& got = AbstractType::Handle(
instantiate_future_or(nullable_future_or_T, type_legacy_object));
EXPECT_TYPES_SYNTACTICALLY_EQUIVALENT(type_nullable_object, got);
}
const auto& type_never = Type::Handle(object_store->never_type());
const auto& type_null = Type::Handle(object_store->null_type());

View file

@ -2762,10 +2762,10 @@ class UntaggedAbstractType : public UntaggedInstance {
kFinalizedUninstantiated, // Uninstantiated type ready for use.
};
using NullabilityBits = BitField<uint32_t, uint8_t, 0, 2>;
static constexpr intptr_t kNullabilityMask = NullabilityBits::mask();
using NullabilityBit = BitField<uint32_t, uint8_t, 0, 1>;
static constexpr intptr_t kNullabilityMask = NullabilityBit::mask();
static constexpr intptr_t kTypeStateShift = NullabilityBits::kNextBit;
static constexpr intptr_t kTypeStateShift = NullabilityBit::kNextBit;
static constexpr intptr_t kTypeStateBits = 2;
using TypeStateBits =
BitField<uint32_t, uint8_t, kTypeStateShift, kTypeStateBits>;

View file

@ -708,15 +708,13 @@ ISOLATE_UNIT_TEST_CASE(SerializeEmptyByteArray) {
VM_UNIT_TEST_CASE(FullSnapshot) {
// clang-format off
auto kScriptChars = Utils::CStringUniquePtr(
OS::SCreate(
nullptr,
const char* kScriptChars =
"class Fields {\n"
" Fields(int i, int j) : fld1 = i, fld2 = j {}\n"
" int fld1;\n"
" final int fld2;\n"
" final int bigint_fld = 0xfffffffffff;\n"
" static int%s fld3;\n"
" static int? fld3;\n"
" static const int smi_sfld = 10;\n"
" static const int bigint_sfld = 0xfffffffffff;\n"
"}\n"
@ -732,9 +730,7 @@ VM_UNIT_TEST_CASE(FullSnapshot) {
" Expect.equals(true, obj.bigint_fld == 0xfffffffffff);\n"
" return obj;\n"
" }\n"
"}\n",
TestCase::NullableTag()),
std::free);
"}\n";
// clang-format on
Dart_Handle result;
@ -747,7 +743,7 @@ VM_UNIT_TEST_CASE(FullSnapshot) {
TestIsolateScope __test_isolate__;
// Create a test library and Load up a test script in it.
TestCase::LoadTestScript(kScriptChars.get(), nullptr);
TestCase::LoadTestScript(kScriptChars, nullptr);
Thread* thread = Thread::Current();
TransitionNativeToVM transition(thread);

View file

@ -159,11 +159,8 @@ static Dart_NativeFunction native_lookup(Dart_Handle name,
// Unit test case to verify stack frame iteration.
TEST_CASE(ValidateStackFrameIteration) {
const char* nullable_tag = TestCase::NullableTag();
// clang-format off
auto kScriptChars = Utils::CStringUniquePtr(
OS::SCreate(
nullptr,
const char* kScriptChars =
"class StackFrame {"
" @pragma('vm:external-name', 'StackFrame_equals')\n"
" external static equals(var obj1, var obj2);\n"
@ -176,21 +173,21 @@ TEST_CASE(ValidateStackFrameIteration) {
"} "
"class First {"
" First() { }"
" int%s method1(int%s param) {"
" int? method1(int? param) {"
" if (param == 1) {"
" param = method2(200);"
" } else {"
" param = method2(100);"
" }"
" }"
" int%s method2(int param) {"
" int? method2(int param) {"
" if (param == 200) {"
" First.staticmethod(this, param);"
" } else {"
" First.staticmethod(this, 10);"
" }"
" }"
" static int%s staticmethod(First obj, int param) {"
" static int? staticmethod(First obj, int param) {"
" if (param == 10) {"
" obj.method3(10);"
" } else {"
@ -211,7 +208,7 @@ TEST_CASE(ValidateStackFrameIteration) {
"}"
"class Second {"
" Second() { }"
" int%s method1(int%s param) {"
" int? method1(int? param) {"
" if (param == 1) {"
" param = method2(200);"
" } else {"
@ -220,10 +217,10 @@ TEST_CASE(ValidateStackFrameIteration) {
" param = obj.method1(2);"
" }"
" }"
" int%s method2(int param) {"
" int? method2(int param) {"
" Second.staticmethod(this, param);"
" }"
" static int%s staticmethod(Second obj, int param) {"
" static int? staticmethod(Second obj, int param) {"
" obj.method3(10);"
" }"
" method3(int param) {"
@ -243,14 +240,10 @@ TEST_CASE(ValidateStackFrameIteration) {
" obj.method1(1);"
" obj.method1(2);"
" }"
"}",
nullable_tag, nullable_tag, nullable_tag, nullable_tag, nullable_tag,
nullable_tag, nullable_tag, nullable_tag),
std::free);
"}";
// clang-format on
Dart_Handle lib = TestCase::LoadTestScript(
kScriptChars.get(),
reinterpret_cast<Dart_NativeEntryResolver>(native_lookup));
kScriptChars, reinterpret_cast<Dart_NativeEntryResolver>(native_lookup));
Dart_Handle cls = Dart_GetClass(lib, NewString("StackFrameTest"));
EXPECT_VALID(Dart_Invoke(cls, NewString("testMain"), 0, nullptr));
}

View file

@ -155,10 +155,8 @@ namespace dart {
V(InstantiateType) \
V(InstantiateTypeNonNullableClassTypeParameter) \
V(InstantiateTypeNullableClassTypeParameter) \
V(InstantiateTypeLegacyClassTypeParameter) \
V(InstantiateTypeNonNullableFunctionTypeParameter) \
V(InstantiateTypeNullableFunctionTypeParameter) \
V(InstantiateTypeLegacyFunctionTypeParameter) \
V(InstantiateTypeArguments) \
V(InstantiateTypeArgumentsMayShareInstantiatorTA) \
V(InstantiateTypeArgumentsMayShareFunctionTA) \

View file

@ -966,9 +966,8 @@ ISOLATE_UNIT_TEST_CASE(TTS_SubtypeRangeCheck) {
// This is a regression test verifying that we don't fall through into
// runtime for Null and Never.
auto& type_nullable_int = Type::Handle(Type::IntType());
type_nullable_int = type_nullable_int.ToNullability(
TestCase::IsNNBD() ? Nullability::kNullable : Nullability::kLegacy,
Heap::kNew);
type_nullable_int =
type_nullable_int.ToNullability(Nullability::kNullable, Heap::kNew);
auto& tav_nullable_int = TypeArguments::Handle(TypeArguments::New(1));
tav_nullable_int.SetTypeAt(0, type_nullable_int);
CanonicalizeTAV(&tav_nullable_int);
@ -978,20 +977,18 @@ ISOLATE_UNIT_TEST_CASE(TTS_SubtypeRangeCheck) {
RunTTSTest(type_base_nullable_int, {obj_base_null, tav_null, tav_null});
RunTTSTest(type_base_nullable_int, {obj_base_never, tav_null, tav_null});
if (TestCase::IsNNBD()) {
// Base<Null|Never> as Base<int>
auto& type_int = Type::Handle(Type::IntType());
type_int = type_int.ToNullability(Nullability::kNonNullable, Heap::kNew);
auto& tav_int = TypeArguments::Handle(TypeArguments::New(1));
tav_int.SetTypeAt(0, type_int);
CanonicalizeTAV(&tav_int);
auto& type_base_int = Type::Handle(Type::New(class_base, tav_int));
type_base_int =
type_base_int.ToNullability(Nullability::kNonNullable, Heap::kNew);
FinalizeAndCanonicalize(&type_base_int);
RunTTSTest(type_base_int, Failure({obj_base_null, tav_null, tav_null}));
RunTTSTest(type_base_int, {obj_base_never, tav_null, tav_null});
}
// Base<Null|Never> as Base<int>
auto& type_int = Type::Handle(Type::IntType());
type_int = type_int.ToNullability(Nullability::kNonNullable, Heap::kNew);
auto& tav_int = TypeArguments::Handle(TypeArguments::New(1));
tav_int.SetTypeAt(0, type_int);
CanonicalizeTAV(&tav_int);
auto& type_base_int = Type::Handle(Type::New(class_base, tav_int));
type_base_int =
type_base_int.ToNullability(Nullability::kNonNullable, Heap::kNew);
FinalizeAndCanonicalize(&type_base_int);
RunTTSTest(type_base_int, Failure({obj_base_null, tav_null, tav_null}));
RunTTSTest(type_base_int, {obj_base_never, tav_null, tav_null});
// <...> as I2
const auto& type_i2 = AbstractType::Handle(class_i2.RareType());
@ -1078,21 +1075,10 @@ ISOLATE_UNIT_TEST_CASE(TTS_GenericSubtypeRangeCheck) {
const auto& type_dynamic = Type::Handle(Type::DynamicType());
auto& type_int = Type::Handle(Type::IntType());
if (!TestCase::IsNNBD()) {
type_int = type_int.ToNullability(Nullability::kLegacy, Heap::kNew);
}
auto& type_string = Type::Handle(Type::StringType());
if (!TestCase::IsNNBD()) {
type_string = type_string.ToNullability(Nullability::kLegacy, Heap::kNew);
}
auto& type_object = Type::Handle(Type::ObjectType());
type_object = type_object.ToNullability(
TestCase::IsNNBD() ? Nullability::kNullable : Nullability::kLegacy,
Heap::kNew);
type_object = type_object.ToNullability(Nullability::kNullable, Heap::kNew);
auto& type_a1 = Type::Handle(class_a1.DeclarationType());
if (!TestCase::IsNNBD()) {
type_a1 = type_a1.ToNullability(Nullability::kLegacy, Heap::kNew);
}
FinalizeAndCanonicalize(&type_a1);
const auto& tav_null = TypeArguments::Handle(TypeArguments::null());
@ -1197,7 +1183,6 @@ ISOLATE_UNIT_TEST_CASE(TTS_GenericSubtypeRangeCheck) {
tav_t.SetTypeAt(0,
TypeParameter::Handle(GetClassTypeParameter(class_base, 0)));
auto& type_a2_t = Type::Handle(Type::New(class_a2, tav_t));
type_a2_t = type_a2_t.ToNullability(Nullability::kLegacy, Heap::kNew);
FinalizeAndCanonicalize(&type_a2_t);
const auto& tav_a2_t = TypeArguments::Handle(TypeArguments::New(1));
tav_a2_t.SetTypeAt(0, type_a2_t);
@ -1213,7 +1198,6 @@ ISOLATE_UNIT_TEST_CASE(TTS_GenericSubtypeRangeCheck) {
const auto& tav_a1 = TypeArguments::Handle(TypeArguments::New(1));
tav_a1.SetTypeAt(0, type_a1);
auto& type_a2_a1 = Type::Handle(Type::New(class_a2, tav_a1));
type_a2_a1 = type_a2_a1.ToNullability(Nullability::kLegacy, Heap::kNew);
FinalizeAndCanonicalize(&type_a2_a1);
const auto& tav_a2_a1 = TypeArguments::Handle(TypeArguments::New(1));
tav_a2_a1.SetTypeAt(0, type_a2_a1);
@ -1348,8 +1332,6 @@ ISOLATE_UNIT_TEST_CASE(TTS_Future) {
const auto& tav_null = Object::null_type_arguments();
const auto& type_object = Type::Handle(
IsolateGroup::Current()->object_store()->non_nullable_object_type());
const auto& type_legacy_object = Type::Handle(
IsolateGroup::Current()->object_store()->legacy_object_type());
const auto& type_nullable_object = Type::Handle(
IsolateGroup::Current()->object_store()->nullable_object_type());
const auto& type_int = Type::Handle(
@ -1369,9 +1351,6 @@ ISOLATE_UNIT_TEST_CASE(TTS_Future) {
auto& tav_object = TypeArguments::Handle(TypeArguments::New(1));
tav_object.SetTypeAt(0, type_object);
CanonicalizeTAV(&tav_object);
auto& tav_legacy_object = TypeArguments::Handle(TypeArguments::New(1));
tav_legacy_object.SetTypeAt(0, type_legacy_object);
CanonicalizeTAV(&tav_legacy_object);
auto& tav_nullable_object = TypeArguments::Handle(TypeArguments::New(1));
tav_nullable_object.SetTypeAt(0, type_nullable_object);
CanonicalizeTAV(&tav_nullable_object);
@ -1394,9 +1373,6 @@ ISOLATE_UNIT_TEST_CASE(TTS_Future) {
auto& type_future_object = Type::Handle(
Type::New(class_future, tav_object, Nullability::kNonNullable));
FinalizeAndCanonicalize(&type_future_object);
auto& type_future_legacy_object = Type::Handle(
Type::New(class_future, tav_legacy_object, Nullability::kNonNullable));
FinalizeAndCanonicalize(&type_future_legacy_object);
auto& type_future_nullable_object = Type::Handle(
Type::New(class_future, tav_nullable_object, Nullability::kNonNullable));
FinalizeAndCanonicalize(&type_future_nullable_object);
@ -1433,7 +1409,6 @@ ISOLATE_UNIT_TEST_CASE(TTS_Future) {
RunTTSTest(type_future, {obj_futureint, tav_null, tav_null});
RunTTSTest(type_future_dynamic, {obj_futureint, tav_null, tav_null});
RunTTSTest(type_future_object, {obj_futureint, tav_null, tav_null});
RunTTSTest(type_future_legacy_object, {obj_futureint, tav_null, tav_null});
RunTTSTest(type_future_nullable_object, {obj_futureint, tav_null, tav_null});
RunTTSTest(type_future_int, {obj_futureint, tav_null, tav_null});
RunTTSTest(type_future_num, {obj_futureint, tav_null, tav_null});
@ -1456,18 +1431,12 @@ ISOLATE_UNIT_TEST_CASE(TTS_Future) {
type_function =
type_function.ToNullability(Nullability::kNonNullable, Heap::kNew);
FinalizeAndCanonicalize(&type_function);
auto& type_legacy_function = Type::Handle(
type_function.ToNullability(Nullability::kLegacy, Heap::kNew));
FinalizeAndCanonicalize(&type_legacy_function);
auto& type_nullable_function = Type::Handle(
type_function.ToNullability(Nullability::kNullable, Heap::kOld));
FinalizeAndCanonicalize(&type_nullable_function);
auto& type_closure = Type::Handle(
Type::New(class_closure, tav_null, Nullability::kNonNullable));
FinalizeAndCanonicalize(&type_closure);
auto& type_legacy_closure = Type::Handle(
type_closure.ToNullability(Nullability::kLegacy, Heap::kOld));
FinalizeAndCanonicalize(&type_legacy_closure);
auto& type_nullable_closure = Type::Handle(
type_closure.ToNullability(Nullability::kNullable, Heap::kOld));
FinalizeAndCanonicalize(&type_nullable_closure);
@ -1481,10 +1450,6 @@ ISOLATE_UNIT_TEST_CASE(TTS_Future) {
type_function_int_nullary.SetParameterTypeAt(0, Type::dynamic_type());
type_function_int_nullary.set_result_type(type_int);
FinalizeAndCanonicalize(&type_function_int_nullary);
auto& type_legacy_function_int_nullary =
FunctionType::Handle(type_function_int_nullary.ToNullability(
Nullability::kLegacy, Heap::kOld));
FinalizeAndCanonicalize(&type_legacy_function_int_nullary);
auto& type_nullable_function_int_nullary =
FunctionType::Handle(type_function_int_nullary.ToNullability(
Nullability::kNullable, Heap::kOld));
@ -1493,29 +1458,18 @@ ISOLATE_UNIT_TEST_CASE(TTS_Future) {
auto& tav_function = TypeArguments::Handle(TypeArguments::New(1));
tav_function.SetTypeAt(0, type_function);
CanonicalizeTAV(&tav_function);
auto& tav_legacy_function = TypeArguments::Handle(TypeArguments::New(1));
tav_legacy_function.SetTypeAt(0, type_legacy_function);
CanonicalizeTAV(&tav_legacy_function);
auto& tav_nullable_function = TypeArguments::Handle(TypeArguments::New(1));
tav_nullable_function.SetTypeAt(0, type_nullable_function);
CanonicalizeTAV(&tav_nullable_function);
auto& tav_closure = TypeArguments::Handle(TypeArguments::New(1));
tav_closure.SetTypeAt(0, type_closure);
CanonicalizeTAV(&tav_closure);
auto& tav_legacy_closure = TypeArguments::Handle(TypeArguments::New(1));
tav_legacy_closure.SetTypeAt(0, type_legacy_closure);
CanonicalizeTAV(&tav_legacy_closure);
auto& tav_nullable_closure = TypeArguments::Handle(TypeArguments::New(1));
tav_nullable_closure.SetTypeAt(0, type_nullable_closure);
CanonicalizeTAV(&tav_nullable_closure);
auto& tav_function_int_nullary = TypeArguments::Handle(TypeArguments::New(1));
tav_function_int_nullary.SetTypeAt(0, type_function_int_nullary);
CanonicalizeTAV(&tav_function_int_nullary);
auto& tav_legacy_function_int_nullary =
TypeArguments::Handle(TypeArguments::New(1));
tav_legacy_function_int_nullary.SetTypeAt(0,
type_legacy_function_int_nullary);
CanonicalizeTAV(&tav_legacy_function_int_nullary);
auto& tav_nullable_function_int_nullary =
TypeArguments::Handle(TypeArguments::New(1));
tav_nullable_function_int_nullary.SetTypeAt(
@ -1525,27 +1479,18 @@ ISOLATE_UNIT_TEST_CASE(TTS_Future) {
auto& type_future_function = Type::Handle(
Type::New(class_future, tav_function, Nullability::kNonNullable));
FinalizeAndCanonicalize(&type_future_function);
auto& type_future_legacy_function = Type::Handle(
Type::New(class_future, tav_legacy_function, Nullability::kNonNullable));
FinalizeAndCanonicalize(&type_future_legacy_function);
auto& type_future_nullable_function = Type::Handle(Type::New(
class_future, tav_nullable_function, Nullability::kNonNullable));
FinalizeAndCanonicalize(&type_future_nullable_function);
auto& type_future_closure = Type::Handle(
Type::New(class_future, tav_closure, Nullability::kNonNullable));
FinalizeAndCanonicalize(&type_future_closure);
auto& type_future_legacy_closure = Type::Handle(
Type::New(class_future, tav_legacy_closure, Nullability::kNonNullable));
FinalizeAndCanonicalize(&type_future_legacy_closure);
auto& type_future_nullable_closure = Type::Handle(
Type::New(class_future, tav_nullable_closure, Nullability::kNonNullable));
FinalizeAndCanonicalize(&type_future_nullable_closure);
auto& type_future_function_int_nullary =
Type::Handle(Type::New(class_future, tav_function_int_nullary));
FinalizeAndCanonicalize(&type_future_function_int_nullary);
auto& type_future_legacy_function_int_nullary =
Type::Handle(Type::New(class_future, tav_legacy_function_int_nullary));
FinalizeAndCanonicalize(&type_future_legacy_function_int_nullary);
auto& type_future_nullable_function_int_nullary =
Type::Handle(Type::New(class_future, tav_nullable_function_int_nullary));
FinalizeAndCanonicalize(&type_future_nullable_function_int_nullary);
@ -1578,23 +1523,16 @@ ISOLATE_UNIT_TEST_CASE(TTS_Future) {
RunTTSTest(type_future_dynamic, {obj_futurefunction, tav_null, tav_null});
RunTTSTest(type_future_nullable_object,
{obj_futurefunction, tav_null, tav_null});
RunTTSTest(type_future_legacy_object,
{obj_futurefunction, tav_null, tav_null});
RunTTSTest(type_future_object, {obj_futurefunction, tav_null, tav_null});
RunTTSTest(type_future_nullable_object,
{obj_futurefunction, tav_null, tav_null});
RunTTSTest(type_future_legacy_object,
{obj_futurefunction, tav_null, tav_null});
RunTTSTest(type_future_object, {obj_futurefunction, tav_null, tav_null});
RunTTSTest(type_future_nullable_function,
{obj_futurefunction, tav_null, tav_null});
RunTTSTest(type_future_legacy_function,
{obj_futurefunction, tav_null, tav_null});
RunTTSTest(type_future_function, {obj_futurefunction, tav_null, tav_null});
RunTTSTest(type_future_t, {obj_futurefunction, tav_null, tav_null});
RunTTSTest(type_future_t,
{obj_futurefunction, tav_nullable_object, tav_null});
RunTTSTest(type_future_t, {obj_futurefunction, tav_legacy_object, tav_null});
RunTTSTest(type_future_t, {obj_futurefunction, tav_object, tav_null});
RunTTSTest(type_future_t,
{obj_futurefunction, tav_function_int_nullary, tav_null});
@ -1612,22 +1550,15 @@ ISOLATE_UNIT_TEST_CASE(TTS_Future) {
//
RunTTSTest(type_future_nullable_function_int_nullary,
FalseNegative({obj_futurefunction, tav_null, tav_null}));
RunTTSTest(type_future_legacy_function_int_nullary,
FalseNegative({obj_futurefunction, tav_null, tav_null}));
RunTTSTest(type_future_function_int_nullary,
FalseNegative({obj_futurefunction, tav_null, tav_null}));
RunTTSTest(type_future_t, FalseNegative({obj_futurefunction,
tav_nullable_function, tav_null}));
RunTTSTest(type_future_t, FalseNegative({obj_futurefunction,
tav_legacy_function, tav_null}));
RunTTSTest(type_future_t,
FalseNegative({obj_futurefunction, tav_function, tav_null}));
RunTTSTest(type_future_t,
FalseNegative({obj_futurefunction,
tav_nullable_function_int_nullary, tav_null}));
RunTTSTest(type_future_t,
FalseNegative({obj_futurefunction, tav_legacy_function_int_nullary,
tav_null}));
// Errors:
// obj as Future<_Closure?> : Type arg is not a supertype
@ -1640,14 +1571,10 @@ ISOLATE_UNIT_TEST_CASE(TTS_Future) {
//
RunTTSTest(type_future_nullable_closure,
Failure({obj_futurefunction, tav_null, tav_null}));
RunTTSTest(type_future_legacy_closure,
Failure({obj_futurefunction, tav_null, tav_null}));
RunTTSTest(type_future_closure,
Failure({obj_futurefunction, tav_null, tav_null}));
RunTTSTest(type_future_t,
Failure({obj_futurefunction, tav_nullable_closure, tav_null}));
RunTTSTest(type_future_t,
Failure({obj_futurefunction, tav_legacy_closure, tav_null}));
RunTTSTest(type_future_t,
Failure({obj_futurefunction, tav_closure, tav_null}));
@ -1680,21 +1607,13 @@ ISOLATE_UNIT_TEST_CASE(TTS_Future) {
{obj_futurenullablefunction, tav_null, tav_null});
RunTTSTest(type_future_nullable_object,
{obj_futurenullablefunction, tav_null, tav_null});
RunTTSTest(type_future_legacy_object,
{obj_futurenullablefunction, tav_null, tav_null});
RunTTSTest(type_future_nullable_object,
{obj_futurefunction, tav_null, tav_null});
RunTTSTest(type_future_legacy_object,
{obj_futurenullablefunction, tav_null, tav_null});
RunTTSTest(type_future_nullable_function,
{obj_futurenullablefunction, tav_null, tav_null});
RunTTSTest(type_future_legacy_function,
{obj_futurenullablefunction, tav_null, tav_null});
RunTTSTest(type_future_t, {obj_futurenullablefunction, tav_null, tav_null});
RunTTSTest(type_future_t,
{obj_futurenullablefunction, tav_nullable_object, tav_null});
RunTTSTest(type_future_t,
{obj_futurenullablefunction, tav_legacy_object, tav_null});
RunTTSTest(type_future_t, {obj_futurenullablefunction,
tav_nullable_function_int_nullary, tav_null});
@ -1714,15 +1633,8 @@ ISOLATE_UNIT_TEST_CASE(TTS_Future) {
RunTTSTest(type_future_nullable_function_int_nullary,
FalseNegative({obj_futurenullablefunction, tav_null, tav_null}));
RunTTSTest(type_future_legacy_function_int_nullary,
FalseNegative({obj_futurenullablefunction, tav_null, tav_null}));
RunTTSTest(type_future_t, FalseNegative({obj_futurenullablefunction,
tav_nullable_function, tav_null}));
RunTTSTest(type_future_t, FalseNegative({obj_futurenullablefunction,
tav_legacy_function, tav_null}));
RunTTSTest(type_future_t,
FalseNegative({obj_futurenullablefunction,
tav_legacy_function_int_nullary, tav_null}));
// Errors:
// obj as Future<_Closure?> : Type arg is not a supertype
@ -1747,14 +1659,10 @@ ISOLATE_UNIT_TEST_CASE(TTS_Future) {
RunTTSTest(type_future_nullable_closure,
Failure({obj_futurenullablefunction, tav_null, tav_null}));
RunTTSTest(type_future_legacy_closure,
Failure({obj_futurenullablefunction, tav_null, tav_null}));
RunTTSTest(type_future_closure,
Failure({obj_futurenullablefunction, tav_null, tav_null}));
RunTTSTest(type_future_t, Failure({obj_futurenullablefunction,
tav_nullable_closure, tav_null}));
RunTTSTest(type_future_t, Failure({obj_futurenullablefunction,
tav_legacy_closure, tav_null}));
RunTTSTest(type_future_t,
Failure({obj_futurenullablefunction, tav_closure, tav_null}));
@ -2021,11 +1929,6 @@ ISOLATE_UNIT_TEST_CASE(TTS_Partial) {
0, Type::Handle(
IsolateGroup::Current()->object_store()->nullable_object_type()));
CanonicalizeTAV(&tav_nullable_object);
auto& tav_legacy_object = TypeArguments::Handle(TypeArguments::New(1));
tav_legacy_object.SetTypeAt(
0, Type::Handle(
IsolateGroup::Current()->object_store()->legacy_object_type()));
CanonicalizeTAV(&tav_legacy_object);
auto& tav_object = TypeArguments::Handle(TypeArguments::New(1));
tav_object.SetTypeAt(
0, Type::Handle(IsolateGroup::Current()->object_store()->object_type()));
@ -2043,9 +1946,6 @@ ISOLATE_UNIT_TEST_CASE(TTS_Partial) {
auto& type_c_nullable =
Type::Handle(Type::New(class_c, tav_null, Nullability::kNullable));
FinalizeAndCanonicalize(&type_c_nullable);
auto& type_c_legacy =
Type::Handle(Type::New(class_c, tav_null, Nullability::kLegacy));
FinalizeAndCanonicalize(&type_c_legacy);
auto& tav_e = TypeArguments::Handle(TypeArguments::New(1));
tav_e.SetTypeAt(0, type_e);
@ -2059,9 +1959,6 @@ ISOLATE_UNIT_TEST_CASE(TTS_Partial) {
auto& tav_nullable_c = TypeArguments::Handle(TypeArguments::New(1));
tav_nullable_c.SetTypeAt(0, type_c_nullable);
CanonicalizeTAV(&tav_nullable_c);
auto& tav_legacy_c = TypeArguments::Handle(TypeArguments::New(1));
tav_legacy_c.SetTypeAt(0, type_c_legacy);
CanonicalizeTAV(&tav_legacy_c);
// One case where optimized TTSes can be partial is if the type is
// uninstantiated with a type parameter at the same position as one of the
@ -2106,13 +2003,10 @@ ISOLATE_UNIT_TEST_CASE(TTS_Partial) {
state.InvokeExistingStub({obj_b_never, tav_null, tav_d});
state.InvokeExistingStub({obj_b_null, tav_null, tav_nullable_c});
state.InvokeExistingStub({obj_b_null, tav_null, tav_legacy_c});
state.InvokeExistingStub(Failure({obj_b_null, tav_null, tav_c}));
state.InvokeExistingStub({obj_b_e, tav_null, tav_nullable_object});
state.InvokeExistingStub({obj_b_e_nullable, tav_null, tav_nullable_object});
state.InvokeExistingStub({obj_b_e, tav_null, tav_legacy_object});
state.InvokeExistingStub({obj_b_e_nullable, tav_null, tav_legacy_object});
state.InvokeExistingStub({obj_b_e, tav_null, tav_object});
state.InvokeExistingStub(Failure({obj_b_e_nullable, tav_null, tav_object}));
}

View file

@ -214,10 +214,6 @@ const char* TestCase::GetTestLib(const char* url) {
return nullptr;
}
bool TestCase::IsNNBD() {
return KernelIsolate::GetExperimentalFlag(ExperimentalFeature::non_nullable);
}
#ifndef PRODUCT
static const char* kIsolateReloadTestLibSource = R"(
@pragma("vm:external-name", "Test_Reload")

View file

@ -415,13 +415,6 @@ class TestCase : TestCaseBase {
static void AddTestLib(const char* url, const char* source);
static const char* GetTestLib(const char* url);
// Return true if non-nullable experiment is enabled.
static bool IsNNBD();
static const char* NullableTag() { return IsNNBD() ? "?" : ""; }
static const char* NullAssertTag() { return IsNNBD() ? "!" : ""; }
static const char* LateTag() { return IsNNBD() ? "late" : ""; }
private:
static Dart_Handle TriggerReload(
std::function<bool(IsolateGroup*, JSONStream*)> do_reload);