From d45c3d15cb3cea0104a87697c085259666eec528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9gis=20Crelier?= Date: Fri, 8 Nov 2019 21:32:48 +0000 Subject: [PATCH] [VM/nnbd] Make Nullability and NNBDMode class enums to avoid name conflicts. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ic78d3f48964bb61cbd1d90a69fcd68b4f29071e4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/124587 Commit-Queue: Régis Crelier Reviewed-by: Alexander Markov --- runtime/lib/mirrors.cc | 9 ++-- .../vm/compiler/frontend/bytecode_reader.cc | 13 ++--- .../compiler/frontend/kernel_fingerprints.cc | 6 +-- .../frontend/kernel_translation_helper.cc | 2 +- runtime/vm/object.cc | 54 +++++++++++-------- runtime/vm/object.h | 39 +++++++++----- runtime/vm/symbols.h | 3 ++ 7 files changed, 76 insertions(+), 50 deletions(-) diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc index 9c8f61708e7..4b63583d915 100644 --- a/runtime/lib/mirrors.cc +++ b/runtime/lib/mirrors.cc @@ -633,16 +633,17 @@ static RawInstance* CreateTypeMirror(const AbstractType& type) { // TODO(regis): Until mirrors reflect nullability, force kLegacy, except for // Null type, which should remain nullable. if (!type.IsNullType()) { - const Type& legacy_type = - Type::Handle(Type::Cast(type).ToNullability(kLegacy, Heap::kOld)); + const Type& legacy_type = Type::Handle( + Type::Cast(type).ToNullability(Nullability::kLegacy, Heap::kOld)); 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. - const TypeParameter& legacy_type = TypeParameter::Handle( - TypeParameter::Cast(type).ToNullability(kLegacy, Heap::kOld)); + const TypeParameter& legacy_type = + TypeParameter::Handle(TypeParameter::Cast(type).ToNullability( + Nullability::kLegacy, Heap::kOld)); return CreateTypeVariableMirror(legacy_type, Object::null_instance()); } UNREACHABLE(); diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc index 528542095eb..176ba621941 100644 --- a/runtime/vm/compiler/frontend/bytecode_reader.cc +++ b/runtime/vm/compiler/frontend/bytecode_reader.cc @@ -502,11 +502,12 @@ void BytecodeReaderHelper::ReadClosureDeclaration(const Function& function, closures_->SetAt(closureIndex, closure); Type& signature_type = Type::Handle( - Z, ReadFunctionSignature( - closure, (flags & kHasOptionalPositionalParamsFlag) != 0, - (flags & kHasOptionalNamedParamsFlag) != 0, - (flags & kHasTypeParamsFlag) != 0, - /* has_positional_param_names = */ true, kNonNullable)); + Z, ReadFunctionSignature(closure, + (flags & kHasOptionalPositionalParamsFlag) != 0, + (flags & kHasOptionalNamedParamsFlag) != 0, + (flags & kHasTypeParamsFlag) != 0, + /* has_positional_param_names = */ true, + Nullability::kNonNullable)); closure.SetSignatureType(signature_type); @@ -1508,7 +1509,7 @@ RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) { const Nullability nullability = bytecode_component_->GetVersion() >= 24 ? static_cast((flags & kNullabilityMask) / kFlagBit4) - : kLegacy; + : Nullability::kLegacy; return ReadType(tag, nullability); } default: diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc index 461913e1693..65c359c7fca 100644 --- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc +++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc @@ -246,7 +246,7 @@ void KernelFingerprintHelper::CalculateDartTypeFingerprint() { break; case kTypeParameterType: { Nullability nullability = ReadNullability(); - BuildHash(nullability); + BuildHash(static_cast(nullability)); ReadUInt(); // read index for parameter. CalculateOptionalDartTypeFingerprint(); // read bound bound. break; @@ -269,7 +269,7 @@ void KernelFingerprintHelper::CalculateOptionalDartTypeFingerprint() { void KernelFingerprintHelper::CalculateInterfaceTypeFingerprint(bool simple) { Nullability nullability = ReadNullability(); - BuildHash(nullability); + BuildHash(static_cast(nullability)); NameIndex kernel_class = ReadCanonicalNameReference(); ASSERT(H.IsClass(kernel_class)); const String& class_name = H.DartClassName(kernel_class); @@ -285,7 +285,7 @@ void KernelFingerprintHelper::CalculateInterfaceTypeFingerprint(bool simple) { void KernelFingerprintHelper::CalculateFunctionTypeFingerprint(bool simple) { Nullability nullability = ReadNullability(); - BuildHash(nullability); + BuildHash(static_cast(nullability)); if (!simple) { CalculateTypeParametersListFingerprint(); // read type_parameters. diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc index 51440d4083e..32c31481a91 100644 --- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc +++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc @@ -2769,7 +2769,7 @@ void TypeTranslator::BuildTypeInternal() { break; case kBottomType: result_ = Class::Handle(Z, I->object_store()->null_class()) - .DeclarationType(kNullable); + .DeclarationType(Nullability::kNullable); ASSERT(result_.IsNullable()); break; case kNeverType: diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index e42dae440ce..5112bc0fc99 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -944,13 +944,13 @@ void Object::Init(Isolate* isolate) { cls.set_is_type_finalized(); cls = dynamic_class_; - *dynamic_type_ = Type::NewNonParameterizedType(cls, kNullable); + *dynamic_type_ = Type::NewNonParameterizedType(cls, Nullability::kNullable); cls = void_class_; - *void_type_ = Type::NewNonParameterizedType(cls, kNullable); + *void_type_ = Type::NewNonParameterizedType(cls, Nullability::kNullable); cls = never_class_; - *never_type_ = Type::NewNonParameterizedType(cls, kNonNullable); + *never_type_ = Type::NewNonParameterizedType(cls, Nullability::kNonNullable); // Since TypeArguments objects are passed as function arguments, make them // behave as Dart instances, although they are just VM objects. @@ -1934,7 +1934,7 @@ RawError* Object::Init(Isolate* isolate, // name is a built-in identifier (this is wrong). The corresponding types // are stored in the object store. cls = object_store->null_class(); - type = Type::NewNonParameterizedType(cls, kNullable); + type = Type::NewNonParameterizedType(cls, Nullability::kNullable); cls.set_declaration_type(type); object_store->set_null_type(type); ASSERT(type.IsNullable()); @@ -4345,7 +4345,7 @@ RawType* Class::DeclarationType(Nullability nullability) const { ASSERT(is_declaration_loaded()); if (IsNullClass()) { // Ignore requested nullability (e.g. by mirrors). - nullability = kNullable; + nullability = Nullability::kNullable; } Type& type = Type::Handle(declaration_type()); if (!type.IsNull()) { @@ -16664,8 +16664,8 @@ RawAbstractType* Instance::GetType(Heap::Space space) const { } // TODO(regis): The runtime type of a non-null instance should be // non-nullable instead of legacy. Revisit. - type = Type::New(cls, type_arguments, TokenPosition::kNoSource, kLegacy, - space); + type = Type::New(cls, type_arguments, TokenPosition::kNoSource, + Nullability::kLegacy, space); type.SetIsFinalized(); type ^= type.Canonicalize(); } @@ -17019,7 +17019,7 @@ TokenPosition AbstractType::token_pos() const { Nullability AbstractType::nullability() const { // AbstractType is an abstract class. UNREACHABLE(); - return kNullable; + return Nullability::kNullable; } bool AbstractType::IsInstantiated(Genericity genericity, @@ -17201,8 +17201,21 @@ RawString* AbstractType::PrintURIs(URIs* uris) { return Symbols::FromConcatAll(thread, pieces); } -// Keep in sync with Nullability enum in runtime/vm/object.h. -static const char* nullability_suffix[4] = {"%", "?", "", "*"}; +static const String& NullabilitySuffix(Nullability value) { + // Keep in sync with Nullability enum in runtime/vm/object.h. + switch (value) { + case Nullability::kUndetermined: + return Symbols::Percent(); + case Nullability::kNullable: + return Symbols::QuestionMark(); + case Nullability::kNonNullable: + return Symbols::Empty(); + case Nullability::kLegacy: + return Symbols::Star(); + default: + UNREACHABLE(); + } +} RawString* AbstractType::BuildName(NameVisibility name_visibility) const { ASSERT(name_visibility != kScrubbedName); @@ -17212,7 +17225,7 @@ RawString* AbstractType::BuildName(NameVisibility name_visibility) const { if (FLAG_show_nullability) { return Symbols::FromConcat( thread, String::Handle(zone, TypeParameter::Cast(*this).name()), - String::Handle(zone, String::New(nullability_suffix[nullability()]))); + NullabilitySuffix(nullability())); } return TypeParameter::Cast(*this).name(); } @@ -17230,8 +17243,7 @@ RawString* AbstractType::BuildName(NameVisibility name_visibility) const { return Symbols::FromConcat( thread, String::Handle(zone, signature_function.UserVisibleSignature()), - String::Handle(zone, - String::New(nullability_suffix[nullability()]))); + NullabilitySuffix(nullability())); } return signature_function.UserVisibleSignature(); } @@ -17241,10 +17253,9 @@ RawString* AbstractType::BuildName(NameVisibility name_visibility) const { if (!IsFinalized() || IsBeingFinalized()) { // TODO(regis): Check if this is dead code. if (FLAG_show_nullability) { - return Symbols::FromConcat( - thread, String::Handle(zone, class_name.raw()), - String::Handle(zone, - String::New(nullability_suffix[nullability()]))); + return Symbols::FromConcat(thread, + String::Handle(zone, class_name.raw()), + NullabilitySuffix(nullability())); } return class_name.raw(); } @@ -17287,8 +17298,7 @@ RawString* AbstractType::BuildName(NameVisibility name_visibility) const { pieces.Add(args_name); } if (FLAG_show_nullability) { - pieces.Add( - String::Handle(zone, String::New(nullability_suffix[nullability()]))); + pieces.Add(NullabilitySuffix(nullability())); } // The name is only used for type checking and debugging purposes. // Unless profiling data shows otherwise, it is not worth caching the name in @@ -17327,7 +17337,7 @@ bool AbstractType::IsTopType(NNBDMode mode) const { return false; } if (cid == kDynamicCid || cid == kVoidCid || - (cid == kInstanceCid && (mode != kStrong || IsNullable()))) { + (cid == kInstanceCid && (mode != NNBDMode::kStrong || IsNullable()))) { return true; } // FutureOr where T is a top type behaves as a top type. @@ -18463,7 +18473,7 @@ void TypeParameter::SetGenericCovariantImpl(bool value) const { } void TypeParameter::set_nullability(Nullability value) const { - StoreNonPointer(&raw_ptr()->nullability_, value); + StoreNonPointer(&raw_ptr()->nullability_, static_cast(value)); } RawTypeParameter* TypeParameter::ToNullability(Nullability value, @@ -18662,7 +18672,7 @@ RawTypeParameter* TypeParameter::New(const Class& parameterized_class, result.set_name(name); result.set_bound(bound); result.set_flags(0); - result.set_nullability(kLegacy); + result.set_nullability(Nullability::kLegacy); result.SetGenericCovariantImpl(is_generic_covariant_impl); result.SetHash(0); result.set_token_pos(token_pos); diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 6749482d06e..21c28d6ddce 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -838,7 +838,7 @@ typedef ZoneGrowableHandlePtrArray* TrailPtr; typedef ZoneGrowableHandlePtrArray URIs; // Keep in sync with package:kernel/lib/ast.dart -enum Nullability { +enum class Nullability { kUndetermined = 0, kNullable = 1, kNonNullable = 2, @@ -846,7 +846,7 @@ enum Nullability { }; // Nullability aware subtype checking modes. -enum NNBDMode { +enum class NNBDMode { kUnaware, kWeak, kStrong, @@ -954,7 +954,8 @@ class Class : public Object { // variant may be requested. The first requested type gets cached in the class // and subsequent nullability variants get cached in the object store. // TODO(regis): Is this caching still useful or should we eliminate it? - RawType* DeclarationType(Nullability nullability = kLegacy) const; + RawType* DeclarationType( + Nullability nullability = Nullability::kLegacy) const; static intptr_t declaration_type_offset() { return OFFSET_OF(RawClass, declaration_type_); @@ -2189,7 +2190,8 @@ class Function : public Object { // function type with uninstantiated type arguments 'T' and 'R' as elements of // its type argument vector. // A function type is non-nullable by default. - RawType* SignatureType(Nullability nullability = kNonNullable) const; + RawType* SignatureType( + Nullability nullability = Nullability::kNonNullable) const; RawType* ExistingSignatureType() const; // Update the signature type (with a canonical version). @@ -6819,10 +6821,18 @@ class AbstractType : public Instance { virtual void SetIsBeingFinalized() const; virtual Nullability nullability() const; - virtual bool IsUndetermined() const { return nullability() == kUndetermined; } - virtual bool IsNullable() const { return nullability() == kNullable; } - virtual bool IsNonNullable() const { return nullability() == kNonNullable; } - virtual bool IsLegacy() const { return nullability() == kLegacy; } + virtual bool IsUndetermined() const { + return nullability() == Nullability::kUndetermined; + } + virtual bool IsNullable() const { + return nullability() == Nullability::kNullable; + } + virtual bool IsNonNullable() const { + return nullability() == Nullability::kNonNullable; + } + virtual bool IsLegacy() const { + return nullability() == Nullability::kLegacy; + } virtual bool HasTypeClass() const { return type_class_id() != kIllegalCid; } virtual classid_t type_class_id() const; @@ -6944,7 +6954,7 @@ class AbstractType : public Instance { // Check if this type represents a top type. // TODO(regis): Remove default kUnaware mode as implementation progresses. - bool IsTopType(NNBDMode mode = kUnaware) const; + bool IsTopType(NNBDMode mode = NNBDMode::kUnaware) const; // Check if this type represents the 'bool' type. bool IsBoolType() const; @@ -7057,8 +7067,8 @@ class Type : public AbstractType { } void set_nullability(Nullability value) const { ASSERT(!IsCanonical()); - ASSERT(value != kUndetermined); - StoreNonPointer(&raw_ptr()->nullability_, value); + ASSERT(value != Nullability::kUndetermined); + StoreNonPointer(&raw_ptr()->nullability_, static_cast(value)); } RawType* ToNullability(Nullability value, Heap::Space space) const; virtual classid_t type_class_id() const; @@ -7157,13 +7167,14 @@ class Type : public AbstractType { static RawType* DartTypeType(); // The finalized type of the given non-parameterized class. - static RawType* NewNonParameterizedType(const Class& type_class, - Nullability nullability = kLegacy); + static RawType* NewNonParameterizedType( + const Class& type_class, + Nullability nullability = Nullability::kLegacy); static RawType* New(const Class& clazz, const TypeArguments& arguments, TokenPosition token_pos, - Nullability nullability = kLegacy, + Nullability nullability = Nullability::kLegacy, Heap::Space space = Heap::kOld); private: diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h index e9aa508067a..cb649510c7b 100644 --- a/runtime/vm/symbols.h +++ b/runtime/vm/symbols.h @@ -580,6 +580,9 @@ class Symbols : public AllStatic { static const String& Percent() { return *(symbol_handles_[kNullCharId + '%']); } + static const String& QuestionMark() { + return *(symbol_handles_[kNullCharId + '?']); + } static const String& Caret() { return *(symbol_handles_[kNullCharId + '^']); } static const String& Tilde() { return *(symbol_handles_[kNullCharId + '~']); }