| Index: runtime/vm/object.cc
|
| diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
|
| index d2ceb636311b0981295abd508214407ee4e7b05b..9e73e8d8a84844b95b56bde14b8404a9fe6ab222 100644
|
| --- a/runtime/vm/object.cc
|
| +++ b/runtime/vm/object.cc
|
| @@ -1150,8 +1150,6 @@ NOT_IN_PRODUCT(
|
|
|
| // Setup type class early in the process.
|
| const Class& type_cls = Class::Handle(zone, Class::New<Type>());
|
| - const Class& function_type_cls = Class::Handle(zone,
|
| - Class::New<FunctionType>());
|
| const Class& type_ref_cls = Class::Handle(zone, Class::New<TypeRef>());
|
| const Class& type_parameter_cls = Class::Handle(zone,
|
| Class::New<TypeParameter>());
|
| @@ -1314,9 +1312,6 @@ NOT_IN_PRODUCT(
|
| RegisterPrivateClass(type_cls, Symbols::Type(), core_lib);
|
| pending_classes.Add(type_cls);
|
|
|
| - RegisterPrivateClass(function_type_cls, Symbols::FunctionType(), core_lib);
|
| - pending_classes.Add(function_type_cls);
|
| -
|
| RegisterPrivateClass(type_ref_cls, Symbols::TypeRef(), core_lib);
|
| pending_classes.Add(type_ref_cls);
|
|
|
| @@ -1633,7 +1628,6 @@ NOT_IN_PRODUCT(
|
|
|
| cls = Class::New<LibraryPrefix>();
|
| cls = Class::New<Type>();
|
| - cls = Class::New<FunctionType>();
|
| cls = Class::New<TypeRef>();
|
| cls = Class::New<TypeParameter>();
|
| cls = Class::New<BoundedType>();
|
| @@ -2426,10 +2420,10 @@ intptr_t Class::NumTypeArguments() const {
|
| break;
|
| }
|
| sup_type = cls.super_type();
|
| - // A BoundedType, TypeRef, or FunctionType can appear as type argument of
|
| + // A BoundedType, TypeRef, or function type can appear as type argument of
|
| // sup_type, but not as sup_type itself.
|
| ASSERT(sup_type.IsType());
|
| - sup_type = ClassFinalizer::ResolveTypeClass(cls, Type::Cast(sup_type));
|
| + ClassFinalizer::ResolveTypeClass(cls, Type::Cast(sup_type));
|
| cls = sup_type.type_class();
|
| ASSERT(!cls.IsTypedefClass());
|
| } while (true);
|
| @@ -3631,8 +3625,8 @@ void Class::DisableAllocationStub() const {
|
| }
|
|
|
|
|
| -bool Class::IsFunctionClass() const {
|
| - return raw() == Type::Handle(Type::Function()).type_class();
|
| +bool Class::IsDartFunctionClass() const {
|
| + return raw() == Type::Handle(Type::DartFunctionType()).type_class();
|
| }
|
|
|
|
|
| @@ -3710,7 +3704,7 @@ bool Class::TypeTestNonRecursive(const Class& cls,
|
| bound_trail,
|
| space);
|
| }
|
| - if (other.IsFunctionClass()) {
|
| + if (other.IsDartFunctionClass()) {
|
| // Check if type S has a call() method.
|
| Function& function = Function::Handle(zone,
|
| thsi.LookupDynamicFunctionAllowAbstract(Symbols::Call()));
|
| @@ -5432,12 +5426,12 @@ void Function::set_implicit_closure_function(const Function& value) const {
|
| }
|
|
|
|
|
| -RawFunctionType* Function::SignatureType() const {
|
| - FunctionType& type = FunctionType::Handle();
|
| +RawType* Function::SignatureType() const {
|
| + Type& type = Type::Handle();
|
| const Object& obj = Object::Handle(raw_ptr()->data_);
|
| if (IsSignatureFunction()) {
|
| - ASSERT(obj.IsNull() || obj.IsFunctionType());
|
| - type = obj.IsNull() ? FunctionType::null() : FunctionType::Cast(obj).raw();
|
| + ASSERT(obj.IsNull() || Type::Cast(obj).IsFunctionType());
|
| + type = obj.IsNull() ? Type::null() : Type::Cast(obj).raw();
|
| } else {
|
| ASSERT(IsClosureFunction());
|
| ASSERT(!obj.IsNull());
|
| @@ -5473,18 +5467,15 @@ RawFunctionType* Function::SignatureType() const {
|
| const TypeArguments& signature_type_arguments =
|
| TypeArguments::Handle(scope_class.type_parameters());
|
| // Return the still unfinalized signature type.
|
| - type = FunctionType::New(scope_class,
|
| - signature_type_arguments,
|
| - *this,
|
| - token_pos());
|
| -
|
| + type = Type::New(scope_class, signature_type_arguments, token_pos());
|
| + type.set_signature(*this);
|
| SetSignatureType(type);
|
| }
|
| return type.raw();
|
| }
|
|
|
|
|
| -void Function::SetSignatureType(const FunctionType& value) const {
|
| +void Function::SetSignatureType(const Type& value) const {
|
| if (IsSignatureFunction()) {
|
| set_data(value);
|
| } else {
|
| @@ -6153,9 +6144,9 @@ bool Function::HasCompatibleParametersWith(const Function& other,
|
| String::Handle(UserVisibleName()).ToCString(),
|
| String::Handle(other.UserVisibleSignature()).ToCString(),
|
| String::Handle(other.UserVisibleName()).ToCString(),
|
| - String::Handle(FunctionType::Handle(
|
| + String::Handle(Type::Handle(
|
| SignatureType()).EnumerateURIs()).ToCString(),
|
| - String::Handle(FunctionType::Handle(
|
| + String::Handle(Type::Handle(
|
| other.SignatureType()).EnumerateURIs()).ToCString());
|
| return false;
|
| }
|
| @@ -6591,8 +6582,7 @@ RawFunction* Function::ImplicitClosureFunction() const {
|
| param_name = ParameterNameAt(has_receiver - kClosure + i);
|
| closure_function.SetParameterNameAt(i, param_name);
|
| }
|
| - const FunctionType& signature_type =
|
| - FunctionType::Handle(closure_function.SignatureType());
|
| + const Type& signature_type = Type::Handle(closure_function.SignatureType());
|
| if (!signature_type.IsFinalized()) {
|
| ClassFinalizer::FinalizeType(
|
| Class::Handle(Owner()), signature_type, ClassFinalizer::kCanonicalize);
|
| @@ -6667,13 +6657,6 @@ void Function::BuildSignatureParameters(
|
| pieces->Add(Symbols::LBrace());
|
| }
|
| for (intptr_t i = num_fixed_params; i < num_params; i++) {
|
| - // The parameter name of an optional positional parameter does not need
|
| - // to be part of the signature, since it is not used.
|
| - if (num_opt_named_params > 0) {
|
| - name = ParameterNameAt(i);
|
| - pieces->Add(name);
|
| - pieces->Add(Symbols::ColonSpace());
|
| - }
|
| param_type = ParameterTypeAt(i);
|
| if (instantiate &&
|
| param_type.IsFinalized() &&
|
| @@ -6684,6 +6667,13 @@ void Function::BuildSignatureParameters(
|
| ASSERT(!param_type.IsNull());
|
| name = param_type.BuildName(name_visibility);
|
| pieces->Add(name);
|
| + // The parameter name of an optional positional parameter does not need
|
| + // to be part of the signature, since it is not used.
|
| + if (num_opt_named_params > 0) {
|
| + name = ParameterNameAt(i);
|
| + pieces->Add(Symbols::Blank());
|
| + pieces->Add(name);
|
| + }
|
| if (i != (num_params - 1)) {
|
| pieces->Add(Symbols::CommaSpace());
|
| }
|
| @@ -6715,7 +6705,7 @@ RawInstance* Function::ImplicitStaticClosure() const {
|
|
|
| RawInstance* Function::ImplicitInstanceClosure(const Instance& receiver) const {
|
| ASSERT(IsImplicitClosureFunction());
|
| - const FunctionType& signature_type = FunctionType::Handle(SignatureType());
|
| + const Type& signature_type = Type::Handle(SignatureType());
|
| const Class& cls = Class::Handle(signature_type.type_class());
|
| const Context& context = Context::Handle(Context::New(1));
|
| context.SetAt(0, receiver);
|
| @@ -7126,7 +7116,7 @@ void ClosureData::set_parent_function(const Function& value) const {
|
| }
|
|
|
|
|
| -void ClosureData::set_signature_type(const FunctionType& value) const {
|
| +void ClosureData::set_signature_type(const Type& value) const {
|
| StorePointer(&raw_ptr()->signature_type_, value.raw());
|
| }
|
|
|
| @@ -12092,6 +12082,7 @@ void ICData::set_arguments_descriptor(const Array& value) const {
|
| StorePointer(&raw_ptr()->args_descriptor_, value.raw());
|
| }
|
|
|
| +
|
| void ICData::set_deopt_id(intptr_t value) const {
|
| ASSERT(value <= kMaxInt32);
|
| StoreNonPointer(&raw_ptr()->deopt_id_, value);
|
| @@ -14611,8 +14602,8 @@ RawAbstractType* Instance::GetType() const {
|
| if (cls.IsClosureClass()) {
|
| const Function& signature =
|
| Function::Handle(Closure::Cast(*this).function());
|
| - FunctionType& type = FunctionType::Handle(signature.SignatureType());
|
| - if (type.scope_class() == cls.raw()) {
|
| + Type& type = Type::Handle(signature.SignatureType());
|
| + if (type.type_class() == cls.raw()) {
|
| // Type is not parameterized.
|
| if (!type.IsCanonical()) {
|
| type ^= type.Canonicalize();
|
| @@ -14620,11 +14611,11 @@ RawAbstractType* Instance::GetType() const {
|
| }
|
| return type.raw();
|
| }
|
| - const Class& scope_cls = Class::Handle(type.scope_class());
|
| + const Class& scope_cls = Class::Handle(type.type_class());
|
| ASSERT(scope_cls.NumTypeArguments() > 0);
|
| TypeArguments& type_arguments = TypeArguments::Handle(GetTypeArguments());
|
| - type = FunctionType::New(
|
| - scope_cls, type_arguments, signature, TokenPosition::kNoSource);
|
| + type = Type::New(scope_cls, type_arguments, TokenPosition::kNoSource);
|
| + type.set_signature(signature);
|
| type.SetIsFinalized();
|
| type ^= type.Canonicalize();
|
| return type.raw();
|
| @@ -14704,13 +14695,13 @@ bool Instance::IsInstanceOf(const AbstractType& other,
|
| if (!instantiated_other.IsFunctionType()) {
|
| return false;
|
| }
|
| - other_signature = FunctionType::Cast(instantiated_other).signature();
|
| + other_signature = Type::Cast(instantiated_other).signature();
|
| other_type_arguments = instantiated_other.arguments();
|
| } else {
|
| if (!other.IsFunctionType()) {
|
| return false;
|
| }
|
| - other_signature = FunctionType::Cast(other).signature();
|
| + other_signature = Type::Cast(other).signature();
|
| other_type_arguments = other.arguments();
|
| }
|
| const Function& signature =
|
| @@ -14775,7 +14766,7 @@ bool Instance::IsInstanceOf(const AbstractType& other,
|
| return true;
|
| }
|
| const Function& other_signature = Function::Handle(
|
| - zone, FunctionType::Cast(instantiated_other).signature());
|
| + zone, Type::Cast(instantiated_other).signature());
|
| if (call.IsSubtypeOf(type_arguments,
|
| other_signature,
|
| other_type_arguments,
|
| @@ -15272,7 +15263,7 @@ RawString* AbstractType::BuildName(NameVisibility name_visibility) const {
|
| if (IsFunctionType()) {
|
| cls = type_class();
|
| const Function& signature_function = Function::Handle(
|
| - zone, FunctionType::Cast(*this).signature());
|
| + zone, Type::Cast(*this).signature());
|
| if (!cls.IsTypedefClass() ||
|
| (cls.signature_function() != signature_function.raw())) {
|
| if (!IsFinalized() || IsBeingFinalized() || IsMalformed()) {
|
| @@ -15377,6 +15368,7 @@ RawString* AbstractType::UserVisibleNameWithURI() const {
|
|
|
|
|
| RawString* AbstractType::ClassName() const {
|
| + ASSERT(!IsFunctionType());
|
| if (HasResolvedTypeClass()) {
|
| return Class::Handle(type_class()).Name();
|
| } else {
|
| @@ -15386,68 +15378,79 @@ RawString* AbstractType::ClassName() const {
|
|
|
|
|
| bool AbstractType::IsNullType() const {
|
| - return HasResolvedTypeClass() &&
|
| + return !IsFunctionType() &&
|
| + HasResolvedTypeClass() &&
|
| (type_class() == Isolate::Current()->object_store()->null_class());
|
| }
|
|
|
|
|
| bool AbstractType::IsBoolType() const {
|
| - return HasResolvedTypeClass() &&
|
| + return !IsFunctionType() &&
|
| + HasResolvedTypeClass() &&
|
| (type_class() == Isolate::Current()->object_store()->bool_class());
|
| }
|
|
|
|
|
| bool AbstractType::IsIntType() const {
|
| - return HasResolvedTypeClass() &&
|
| + return !IsFunctionType() &&
|
| + HasResolvedTypeClass() &&
|
| (type_class() == Type::Handle(Type::IntType()).type_class());
|
| }
|
|
|
|
|
| bool AbstractType::IsDoubleType() const {
|
| - return HasResolvedTypeClass() &&
|
| + return !IsFunctionType() &&
|
| + HasResolvedTypeClass() &&
|
| (type_class() == Type::Handle(Type::Double()).type_class());
|
| }
|
|
|
|
|
| bool AbstractType::IsFloat32x4Type() const {
|
| - return HasResolvedTypeClass() &&
|
| + return !IsFunctionType() &&
|
| + HasResolvedTypeClass() &&
|
| (type_class() == Type::Handle(Type::Float32x4()).type_class());
|
| }
|
|
|
|
|
| bool AbstractType::IsFloat64x2Type() const {
|
| - return HasResolvedTypeClass() &&
|
| + return !IsFunctionType() &&
|
| + HasResolvedTypeClass() &&
|
| (type_class() == Type::Handle(Type::Float64x2()).type_class());
|
| }
|
|
|
|
|
| bool AbstractType::IsInt32x4Type() const {
|
| - return HasResolvedTypeClass() &&
|
| + return !IsFunctionType() &&
|
| + HasResolvedTypeClass() &&
|
| (type_class() == Type::Handle(Type::Int32x4()).type_class());
|
| }
|
|
|
|
|
| bool AbstractType::IsNumberType() const {
|
| - return HasResolvedTypeClass() &&
|
| + return !IsFunctionType() &&
|
| + HasResolvedTypeClass() &&
|
| (type_class() == Type::Handle(Type::Number()).type_class());
|
| }
|
|
|
|
|
| bool AbstractType::IsSmiType() const {
|
| - return HasResolvedTypeClass() &&
|
| + return !IsFunctionType() &&
|
| + HasResolvedTypeClass() &&
|
| (type_class() == Type::Handle(Type::SmiType()).type_class());
|
| }
|
|
|
|
|
| bool AbstractType::IsStringType() const {
|
| - return HasResolvedTypeClass() &&
|
| + return !IsFunctionType() &&
|
| + HasResolvedTypeClass() &&
|
| (type_class() == Type::Handle(Type::StringType()).type_class());
|
| }
|
|
|
|
|
| bool AbstractType::IsDartFunctionType() const {
|
| - return HasResolvedTypeClass() &&
|
| - (type_class() == Type::Handle(Type::Function()).type_class());
|
| + return !IsFunctionType() &&
|
| + HasResolvedTypeClass() &&
|
| + (type_class() == Type::Handle(Type::DartFunctionType()).type_class());
|
| }
|
|
|
|
|
| @@ -15545,7 +15548,7 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
|
| // We may be checking bounds at finalization time and can encounter
|
| // a still unfinalized bound. Finalizing the bound here may lead to cycles.
|
| if (!bound.IsFinalized()) {
|
| - return false; // TODO(regis): Return "maybe after instantiation".
|
| + return false; // TODO(regis): Return "maybe after instantiation".
|
| }
|
| // The current bound_trail cannot be used, because operands are swapped and
|
| // the test is different anyway (more specific vs. subtype).
|
| @@ -15566,10 +15569,10 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
|
| return true;
|
| }
|
| const Function& other_fun =
|
| - Function::Handle(zone, FunctionType::Cast(other).signature());
|
| + Function::Handle(zone, Type::Cast(other).signature());
|
| // Check for two function types.
|
| const Function& fun =
|
| - Function::Handle(zone, FunctionType::Cast(*this).signature());
|
| + Function::Handle(zone, Type::Cast(*this).signature());
|
| return fun.TypeTest(test_kind,
|
| TypeArguments::Handle(zone, arguments()),
|
| other_fun,
|
| @@ -15593,7 +15596,7 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
|
| function.TypeTest(test_kind,
|
| TypeArguments::Handle(zone, arguments()),
|
| Function::Handle(
|
| - zone, FunctionType::Cast(other).signature()),
|
| + zone, Type::Cast(other).signature()),
|
| TypeArguments::Handle(zone, other.arguments()),
|
| bound_error,
|
| space)) {
|
| @@ -15703,7 +15706,7 @@ RawType* Type::ArrayType() {
|
| }
|
|
|
|
|
| -RawType* Type::Function() {
|
| +RawType* Type::DartFunctionType() {
|
| return Isolate::Current()->object_store()->function_type();
|
| }
|
|
|
| @@ -15735,6 +15738,13 @@ void Type::SetIsFinalized() const {
|
| }
|
|
|
|
|
| +void Type::ResetIsFinalized() const {
|
| + ASSERT(IsFinalized());
|
| + set_type_state(RawType::kBeingFinalized);
|
| + SetIsFinalized();
|
| +}
|
| +
|
| +
|
| void Type::SetIsBeingFinalized() const {
|
| ASSERT(IsResolved() && !IsFinalized() && !IsBeingFinalized());
|
| set_type_state(RawType::kBeingFinalized);
|
| @@ -15742,31 +15752,40 @@ void Type::SetIsBeingFinalized() const {
|
|
|
|
|
| bool Type::IsMalformed() const {
|
| - if (raw_ptr()->error_ == LanguageError::null()) {
|
| - return false;
|
| + if (raw_ptr()->sig_or_err_.error_ == LanguageError::null()) {
|
| + return false; // Valid type, but not a function type.
|
| }
|
| const LanguageError& type_error = LanguageError::Handle(error());
|
| + if (type_error.IsNull()) {
|
| + return false; // Valid function type.
|
| + }
|
| return type_error.kind() == Report::kMalformedType;
|
| }
|
|
|
|
|
| bool Type::IsMalbounded() const {
|
| - if (!Isolate::Current()->type_checks()) {
|
| - return false;
|
| + if (raw_ptr()->sig_or_err_.error_ == LanguageError::null()) {
|
| + return false; // Valid type, but not a function type.
|
| }
|
| - if (raw_ptr()->error_ == LanguageError::null()) {
|
| + if (!Isolate::Current()->type_checks()) {
|
| return false;
|
| }
|
| const LanguageError& type_error = LanguageError::Handle(error());
|
| + if (type_error.IsNull()) {
|
| + return false; // Valid function type.
|
| + }
|
| return type_error.kind() == Report::kMalboundedType;
|
| }
|
|
|
|
|
| bool Type::IsMalformedOrMalbounded() const {
|
| - if (raw_ptr()->error_ == LanguageError::null()) {
|
| - return false;
|
| + if (raw_ptr()->sig_or_err_.error_ == LanguageError::null()) {
|
| + return false; // Valid type, but not a function type.
|
| }
|
| const LanguageError& type_error = LanguageError::Handle(error());
|
| + if (type_error.IsNull()) {
|
| + return false; // Valid function type.
|
| + }
|
| if (type_error.kind() == Report::kMalformedType) {
|
| return true;
|
| }
|
| @@ -15775,15 +15794,40 @@ bool Type::IsMalformedOrMalbounded() const {
|
| }
|
|
|
|
|
| +RawLanguageError* Type::error() const {
|
| + const Object& type_error = Object::Handle(raw_ptr()->sig_or_err_.error_);
|
| + if (type_error.IsLanguageError()) {
|
| + return LanguageError::RawCast(type_error.raw());
|
| + }
|
| + return LanguageError::null();
|
| +}
|
| +
|
| +
|
| void Type::set_error(const LanguageError& value) const {
|
| - StorePointer(&raw_ptr()->error_, value.raw());
|
| + StorePointer(&raw_ptr()->sig_or_err_.error_, value.raw());
|
| +}
|
| +
|
| +
|
| +RawFunction* Type::signature() const {
|
| + if (raw_ptr()->sig_or_err_.signature_ == Function::null()) {
|
| + return Function::null();
|
| + }
|
| + const Object& obj = Object::Handle(raw_ptr()->sig_or_err_.signature_);
|
| + if (obj.IsFunction()) {
|
| + return Function::RawCast(obj.raw());
|
| + }
|
| + ASSERT(obj.IsLanguageError()); // Type is malformed or malbounded.
|
| + return Function::null();
|
| +}
|
| +
|
| +
|
| +void Type::set_signature(const Function& value) const {
|
| + StorePointer(&raw_ptr()->sig_or_err_.signature_, value.raw());
|
| }
|
|
|
|
|
| void Type::SetIsResolved() const {
|
| ASSERT(!IsResolved());
|
| - // A Typedef is a FunctionType, not a type.
|
| - ASSERT(!Class::Handle(type_class()).IsTypedefClass());
|
| set_type_state(RawType::kResolved);
|
| }
|
|
|
| @@ -15884,6 +15928,18 @@ RawAbstractType* Type::InstantiateFrom(
|
| // with different instantiators. Allocate a new instantiated version of it.
|
| const Type& instantiated_type =
|
| Type::Handle(zone, Type::New(cls, type_arguments, token_pos(), space));
|
| + // Preserve the bound error if any.
|
| + if (IsMalbounded()) {
|
| + const LanguageError& bound_error = LanguageError::Handle(zone, error());
|
| + instantiated_type.set_error(bound_error);
|
| + }
|
| + // Preserve the signature if this type represents a function type.
|
| + // Note that the types in the signature remain unchanged. They get indirectly
|
| + // instantiated by instantiating the type arguments above.
|
| + const Function& sig_fun = Function::Handle(zone, signature());
|
| + if (!sig_fun.IsNull()) {
|
| + instantiated_type.set_signature(sig_fun);
|
| + }
|
| if (IsFinalized()) {
|
| instantiated_type.SetIsFinalized();
|
| } else {
|
| @@ -15910,67 +15966,142 @@ bool Type::IsEquivalent(const Instance& other, TrailPtr trail) const {
|
| return false;
|
| }
|
| const Type& other_type = Type::Cast(other);
|
| + if (IsFunctionType() != other_type.IsFunctionType()) {
|
| + return false;
|
| + }
|
| ASSERT(IsResolved() && other_type.IsResolved());
|
| if (IsMalformed() || other_type.IsMalformed()) {
|
| - return false;
|
| + return false; // Malformed types do not get canonicalized.
|
| + }
|
| + if (IsMalbounded() != other_type.IsMalbounded()) {
|
| + return false; // Do not drop bound error.
|
| }
|
| if (type_class() != other_type.type_class()) {
|
| return false;
|
| }
|
| if (!IsFinalized() || !other_type.IsFinalized()) {
|
| - return false;
|
| + return false; // Too early to decide if equal.
|
| }
|
| - if (arguments() == other_type.arguments()) {
|
| + if ((arguments() == other_type.arguments()) &&
|
| + (signature() == other_type.signature())) {
|
| return true;
|
| }
|
| Thread* thread = Thread::Current();
|
| Zone* zone = thread->zone();
|
| + if (arguments() != other_type.arguments()) {
|
| const Class& cls = Class::Handle(zone, type_class());
|
| - const intptr_t num_type_params = cls.NumTypeParameters(thread);
|
| - if (num_type_params == 0) {
|
| - // Shortcut unnecessary handle allocation below.
|
| + const intptr_t num_type_params = cls.NumTypeParameters(thread);
|
| + // Shortcut unnecessary handle allocation below if non-generic.
|
| + if (num_type_params > 0) {
|
| + const intptr_t num_type_args = cls.NumTypeArguments();
|
| + const intptr_t from_index = num_type_args - num_type_params;
|
| + const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
|
| + const TypeArguments& other_type_args = TypeArguments::Handle(
|
| + zone, other_type.arguments());
|
| + if (type_args.IsNull()) {
|
| + // Ignore from_index.
|
| + if (!other_type_args.IsRaw(0, num_type_args)) {
|
| + return false;
|
| + }
|
| + } else if (other_type_args.IsNull()) {
|
| + // Ignore from_index.
|
| + if (!type_args.IsRaw(0, num_type_args)) {
|
| + return false;
|
| + }
|
| + } else if (!type_args.IsSubvectorEquivalent(other_type_args,
|
| + from_index,
|
| + num_type_params)) {
|
| + return false;
|
| + }
|
| +#ifdef DEBUG
|
| + if (from_index > 0) {
|
| + // Verify that the type arguments of the super class match, since they
|
| + // depend solely on the type parameters that were just verified to
|
| + // match.
|
| + ASSERT(type_args.Length() >= (from_index + num_type_params));
|
| + ASSERT(other_type_args.Length() >= (from_index + num_type_params));
|
| + AbstractType& type_arg = AbstractType::Handle(zone);
|
| + AbstractType& other_type_arg = AbstractType::Handle(zone);
|
| + for (intptr_t i = 0; i < from_index; i++) {
|
| + type_arg = type_args.TypeAt(i);
|
| + other_type_arg = other_type_args.TypeAt(i);
|
| + // Ignore bounds of bounded types.
|
| + while (type_arg.IsBoundedType()) {
|
| + type_arg = BoundedType::Cast(type_arg).type();
|
| + }
|
| + while (other_type_arg.IsBoundedType()) {
|
| + other_type_arg = BoundedType::Cast(other_type_arg).type();
|
| + }
|
| + ASSERT(type_arg.IsEquivalent(other_type_arg, trail));
|
| + }
|
| + }
|
| +#endif
|
| + }
|
| + }
|
| + if (!IsFunctionType()) {
|
| return true;
|
| }
|
| - const intptr_t num_type_args = cls.NumTypeArguments();
|
| - const intptr_t from_index = num_type_args - num_type_params;
|
| - const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
|
| - const TypeArguments& other_type_args = TypeArguments::Handle(
|
| - zone, other_type.arguments());
|
| - if (type_args.IsNull()) {
|
| - // Ignore from_index.
|
| - return other_type_args.IsRaw(0, num_type_args);
|
| + ASSERT(Type::Cast(other).IsFunctionType());
|
| + // Equal function types must have equal signature types and equal optional
|
| + // named arguments.
|
| + if (signature() == other_type.signature()) {
|
| + return true;
|
| }
|
| - if (other_type_args.IsNull()) {
|
| - // Ignore from_index.
|
| - return type_args.IsRaw(0, num_type_args);
|
| + const Function& sig_fun = Function::Handle(zone, signature());
|
| + const Function& other_sig_fun = Function::Handle(
|
| + zone, other_type.signature());
|
| +
|
| + // Compare number of function parameters.
|
| + const intptr_t num_fixed_params = sig_fun.num_fixed_parameters();
|
| + const intptr_t other_num_fixed_params = other_sig_fun.num_fixed_parameters();
|
| + if (num_fixed_params != other_num_fixed_params) {
|
| + return false;
|
| }
|
| - if (!type_args.IsSubvectorEquivalent(other_type_args,
|
| - from_index,
|
| - num_type_params)) {
|
| + const intptr_t num_opt_pos_params = sig_fun.NumOptionalPositionalParameters();
|
| + const intptr_t other_num_opt_pos_params =
|
| + other_sig_fun.NumOptionalPositionalParameters();
|
| + if (num_opt_pos_params != other_num_opt_pos_params) {
|
| return false;
|
| }
|
| -#ifdef DEBUG
|
| - if (from_index > 0) {
|
| - // Verify that the type arguments of the super class match, since they
|
| - // depend solely on the type parameters that were just verified to match.
|
| - ASSERT(type_args.Length() >= (from_index + num_type_params));
|
| - ASSERT(other_type_args.Length() >= (from_index + num_type_params));
|
| - AbstractType& type_arg = AbstractType::Handle(zone);
|
| - AbstractType& other_type_arg = AbstractType::Handle(zone);
|
| - for (intptr_t i = 0; i < from_index; i++) {
|
| - type_arg = type_args.TypeAt(i);
|
| - other_type_arg = other_type_args.TypeAt(i);
|
| - // Ignore bounds of bounded types.
|
| - while (type_arg.IsBoundedType()) {
|
| - type_arg = BoundedType::Cast(type_arg).type();
|
| - }
|
| - while (other_type_arg.IsBoundedType()) {
|
| - other_type_arg = BoundedType::Cast(other_type_arg).type();
|
| - }
|
| - ASSERT(type_arg.IsEquivalent(other_type_arg, trail));
|
| + const intptr_t num_opt_named_params = sig_fun.NumOptionalNamedParameters();
|
| + const intptr_t other_num_opt_named_params =
|
| + other_sig_fun.NumOptionalNamedParameters();
|
| + if (num_opt_named_params != other_num_opt_named_params) {
|
| + return false;
|
| + }
|
| + const intptr_t num_ignored_params = sig_fun.NumImplicitParameters();
|
| + const intptr_t other_num_ignored_params =
|
| + other_sig_fun.NumImplicitParameters();
|
| + if (num_ignored_params != other_num_ignored_params) {
|
| + return false;
|
| + }
|
| + AbstractType& param_type = Type::Handle(zone);
|
| + AbstractType& other_param_type = Type::Handle(zone);
|
| + // Check the result type.
|
| + param_type = sig_fun.result_type();
|
| + other_param_type = other_sig_fun.result_type();
|
| + if (!param_type.Equals(other_param_type)) {
|
| + return false;
|
| + }
|
| + // Check the types of all parameters.
|
| + const intptr_t num_params = sig_fun.NumParameters();
|
| + ASSERT(other_sig_fun.NumParameters() == num_params);
|
| + for (intptr_t i = 0; i < num_params; i++) {
|
| + param_type = sig_fun.ParameterTypeAt(i);
|
| + other_param_type = other_sig_fun.ParameterTypeAt(i);
|
| + if (!param_type.Equals(other_param_type)) {
|
| + return false;
|
| + }
|
| + }
|
| + // Check the names and types of optional named parameters.
|
| + if (num_opt_named_params == 0) {
|
| + return true;
|
| + }
|
| + for (intptr_t i = num_fixed_params; i < num_params; i++) {
|
| + if (sig_fun.ParameterNameAt(i) != other_sig_fun.ParameterNameAt(i)) {
|
| + return false;
|
| }
|
| }
|
| -#endif
|
| return true;
|
| }
|
|
|
| @@ -15987,10 +16118,43 @@ RawAbstractType* Type::CloneUnfinalized() const {
|
| }
|
| ASSERT(!IsMalformed()); // Malformed types are finalized.
|
| ASSERT(!IsBeingFinalized()); // Cloning must occur prior to finalization.
|
| - TypeArguments& type_args = TypeArguments::Handle(arguments());
|
| - type_args = type_args.CloneUnfinalized();
|
| - const Type& clone = Type::Handle(
|
| - Type::New(Class::Handle(type_class()), type_args, token_pos()));
|
| + Zone* zone = Thread::Current()->zone();
|
| + const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
|
| + const TypeArguments& type_args_clone =
|
| + TypeArguments::Handle(zone, type_args.CloneUnfinalized());
|
| + if (type_args_clone.raw() == type_args.raw()) {
|
| + return raw();
|
| + }
|
| + const Type& clone = Type::Handle(zone,
|
| + Type::New(Class::Handle(zone, type_class()), type_args, token_pos()));
|
| + // Preserve the bound error if any.
|
| + if (IsMalbounded()) {
|
| + const LanguageError& bound_error = LanguageError::Handle(zone, error());
|
| + clone.set_error(bound_error);
|
| + }
|
| + // Clone the signature if this type represents a function type.
|
| + Function& fun = Function::Handle(zone, signature());
|
| + if (!fun.IsNull()) {
|
| + const Class& owner = Class::Handle(zone, fun.Owner());
|
| + Function& fun_clone = Function::Handle(zone,
|
| + Function::NewSignatureFunction(owner, TokenPosition::kNoSource));
|
| + AbstractType& type = AbstractType::Handle(zone, fun.result_type());
|
| + type = type.CloneUnfinalized();
|
| + fun_clone.set_result_type(type);
|
| + const intptr_t num_params = fun.NumParameters();
|
| + fun_clone.set_num_fixed_parameters(fun.num_fixed_parameters());
|
| + fun_clone.SetNumOptionalParameters(fun.NumOptionalParameters(),
|
| + fun.HasOptionalPositionalParameters());
|
| + fun_clone.set_parameter_types(Array::Handle(Array::New(num_params,
|
| + Heap::kOld)));
|
| + for (intptr_t i = 0; i < num_params; i++) {
|
| + type = fun.ParameterTypeAt(i);
|
| + type = type.CloneUnfinalized();
|
| + fun_clone.SetParameterTypeAt(i, type);
|
| + }
|
| + fun_clone.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
|
| + clone.set_signature(fun_clone);
|
| + }
|
| clone.SetIsResolved();
|
| return clone.raw();
|
| }
|
| @@ -16005,14 +16169,42 @@ RawAbstractType* Type::CloneUninstantiated(const Class& new_owner,
|
| }
|
| // We may recursively encounter a type already being cloned, because we clone
|
| // the upper bounds of its uninstantiated type arguments in the same pass.
|
| - Type& clone = Type::Handle();
|
| + Zone* zone = Thread::Current()->zone();
|
| + Type& clone = Type::Handle(zone);
|
| clone ^= OnlyBuddyInTrail(trail);
|
| if (!clone.IsNull()) {
|
| return clone.raw();
|
| }
|
| - const Class& type_cls = Class::Handle(type_class());
|
| - clone = Type::New(type_cls, TypeArguments::Handle(), token_pos());
|
| - TypeArguments& type_args = TypeArguments::Handle(arguments());
|
| + const Class& type_cls = Class::Handle(zone, type_class());
|
| + clone = Type::New(type_cls, TypeArguments::Handle(zone), token_pos());
|
| + // Preserve the bound error if any.
|
| + if (IsMalbounded()) {
|
| + const LanguageError& bound_error = LanguageError::Handle(zone, error());
|
| + clone.set_error(bound_error);
|
| + }
|
| + // Clone the signature if this type represents a function type.
|
| + const Function& fun = Function::Handle(zone, signature());
|
| + if (!fun.IsNull()) {
|
| + Function& fun_clone = Function::Handle(zone,
|
| + Function::NewSignatureFunction(new_owner, TokenPosition::kNoSource));
|
| + AbstractType& type = AbstractType::Handle(zone, fun.result_type());
|
| + type = type.CloneUninstantiated(new_owner, trail);
|
| + fun_clone.set_result_type(type);
|
| + const intptr_t num_params = fun.NumParameters();
|
| + fun_clone.set_num_fixed_parameters(fun.num_fixed_parameters());
|
| + fun_clone.SetNumOptionalParameters(fun.NumOptionalParameters(),
|
| + fun.HasOptionalPositionalParameters());
|
| + fun_clone.set_parameter_types(Array::Handle(Array::New(num_params,
|
| + Heap::kOld)));
|
| + for (intptr_t i = 0; i < num_params; i++) {
|
| + type = fun.ParameterTypeAt(i);
|
| + type = type.CloneUninstantiated(new_owner, trail);
|
| + fun_clone.SetParameterTypeAt(i, type);
|
| + }
|
| + fun_clone.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
|
| + clone.set_signature(fun_clone);
|
| + }
|
| + TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
|
| // Upper bounds of uninstantiated type arguments may form a cycle.
|
| if (type_args.IsRecursive() || !type_args.IsInstantiated()) {
|
| AddOnlyBuddyToTrail(&trail, clone);
|
| @@ -16035,12 +16227,12 @@ RawAbstractType* Type::Canonicalize(TrailPtr trail) const {
|
| Isolate* isolate = thread->isolate();
|
| AbstractType& type = Type::Handle(zone);
|
| const Class& cls = Class::Handle(zone, type_class());
|
| - ASSERT(!cls.IsTypedefClass()); // This type should be a FunctionType.
|
| if (cls.raw() == Object::dynamic_class() && (isolate != Dart::vm_isolate())) {
|
| return Object::dynamic_type().raw();
|
| }
|
| // Fast canonical lookup/registry for simple types.
|
| if (!cls.IsGeneric() && !cls.IsClosureClass()) {
|
| + ASSERT(!IsFunctionType() || cls.IsTypedefClass());
|
| type = cls.CanonicalType();
|
| if (type.IsNull()) {
|
| ASSERT(!cls.raw()->IsVMHeapObject() || (isolate == Dart::vm_isolate()));
|
| @@ -16104,11 +16296,38 @@ RawAbstractType* Type::Canonicalize(TrailPtr trail) const {
|
| if (IsCanonical()) {
|
| // Canonicalizing type_args canonicalized this type as a side effect.
|
| ASSERT(IsRecursive());
|
| + // Cycles via typedefs are detected and disallowed, but a function type can
|
| + // be recursive due to a cycle in its type arguments.
|
| return this->raw();
|
| }
|
| set_arguments(type_args);
|
| ASSERT(type_args.IsNull() || type_args.IsOld());
|
|
|
| + // In case of a function type, replace the actual function by a signature
|
| + // function.
|
| + if (IsFunctionType()) {
|
| + const Function& fun = Function::Handle(zone, signature());
|
| + if (!fun.IsSignatureFunction()) {
|
| + Function& sig_fun = Function::Handle(zone,
|
| + Function::NewSignatureFunction(cls, TokenPosition::kNoSource));
|
| + type = fun.result_type();
|
| + type = type.Canonicalize(trail);
|
| + sig_fun.set_result_type(type);
|
| + const intptr_t num_params = fun.NumParameters();
|
| + sig_fun.set_num_fixed_parameters(fun.num_fixed_parameters());
|
| + sig_fun.SetNumOptionalParameters(fun.NumOptionalParameters(),
|
| + fun.HasOptionalPositionalParameters());
|
| + sig_fun.set_parameter_types(Array::Handle(Array::New(num_params,
|
| + Heap::kOld)));
|
| + for (intptr_t i = 0; i < num_params; i++) {
|
| + type = fun.ParameterTypeAt(i);
|
| + type = type.Canonicalize(trail);
|
| + sig_fun.SetParameterTypeAt(i, type);
|
| + }
|
| + sig_fun.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
|
| + set_signature(sig_fun);
|
| + }
|
| + }
|
| return cls.LookupOrAddCanonicalType(*this, index);
|
| }
|
|
|
| @@ -16119,15 +16338,32 @@ RawString* Type::EnumerateURIs() const {
|
| }
|
| Zone* zone = Thread::Current()->zone();
|
| GrowableHandlePtrArray<const String> pieces(zone, 6);
|
| - const Class& cls = Class::Handle(zone, type_class());
|
| - pieces.Add(Symbols::TwoSpaces());
|
| - pieces.Add(String::Handle(zone, cls.UserVisibleName()));
|
| - pieces.Add(Symbols::SpaceIsFromSpace());
|
| - const Library& library = Library::Handle(zone, cls.library());
|
| - pieces.Add(String::Handle(zone, library.url()));
|
| - pieces.Add(Symbols::NewLine());
|
| - const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
|
| - pieces.Add(String::Handle(zone, type_args.EnumerateURIs()));
|
| + if (IsFunctionType()) {
|
| + // The scope class and type arguments do not appear explicitly in the user
|
| + // visible name. The type arguments were used to instantiate the function
|
| + // type prior to this call.
|
| + const Function& sig_fun = Function::Handle(zone, signature());
|
| + AbstractType& type = AbstractType::Handle(zone);
|
| + const intptr_t num_params = sig_fun.NumParameters();
|
| + GrowableHandlePtrArray<const String> pieces(zone, num_params + 1);
|
| + for (intptr_t i = 0; i < num_params; i++) {
|
| + type = sig_fun.ParameterTypeAt(i);
|
| + pieces.Add(String::Handle(zone, type.EnumerateURIs()));
|
| + }
|
| + // Handle result type last, since it appears last in the user visible name.
|
| + type = sig_fun.result_type();
|
| + pieces.Add(String::Handle(zone, type.EnumerateURIs()));
|
| + } else {
|
| + const Class& cls = Class::Handle(zone, type_class());
|
| + pieces.Add(Symbols::TwoSpaces());
|
| + pieces.Add(String::Handle(zone, cls.UserVisibleName()));
|
| + pieces.Add(Symbols::SpaceIsFromSpace());
|
| + const Library& library = Library::Handle(zone, cls.library());
|
| + pieces.Add(String::Handle(zone, library.url()));
|
| + pieces.Add(Symbols::NewLine());
|
| + const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
|
| + pieces.Add(String::Handle(zone, type_args.EnumerateURIs()));
|
| + }
|
| return Symbols::FromConcatAll(pieces);
|
| }
|
|
|
| @@ -16138,6 +16374,24 @@ intptr_t Type::Hash() const {
|
| if (IsMalformed()) return result;
|
| result = CombineHashes(result, Class::Handle(type_class()).id());
|
| result = CombineHashes(result, TypeArguments::Handle(arguments()).Hash());
|
| + if (IsFunctionType()) {
|
| + const Function& sig_fun = Function::Handle(signature());
|
| + AbstractType& type = AbstractType::Handle(sig_fun.result_type());
|
| + result = CombineHashes(result, type.Hash());
|
| + result = CombineHashes(result, sig_fun.NumOptionalPositionalParameters());
|
| + const intptr_t num_params = sig_fun.NumParameters();
|
| + for (intptr_t i = 0; i < num_params; i++) {
|
| + type = sig_fun.ParameterTypeAt(i);
|
| + result = CombineHashes(result, type.Hash());
|
| + }
|
| + if (sig_fun.NumOptionalNamedParameters() > 0) {
|
| + String& param_name = String::Handle();
|
| + for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) {
|
| + param_name = sig_fun.ParameterNameAt(i);
|
| + result = CombineHashes(result, param_name.Hash());
|
| + }
|
| + }
|
| + }
|
| return FinalizeHash(result);
|
| }
|
|
|
| @@ -16189,558 +16443,71 @@ void Type::set_type_state(int8_t state) const {
|
|
|
|
|
| const char* Type::ToCString() const {
|
| + Zone* zone = Thread::Current()->zone();
|
| const char* unresolved = IsResolved() ? "" : "Unresolved ";
|
| - const TypeArguments& type_arguments = TypeArguments::Handle(arguments());
|
| + const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
|
| + const char* args_cstr = type_args.IsNull() ? "null" : type_args.ToCString();
|
| + Class& cls = Class::Handle(zone);
|
| const char* class_name;
|
| if (HasResolvedTypeClass()) {
|
| - class_name = String::Handle(
|
| - Class::Handle(type_class()).Name()).ToCString();
|
| + cls = type_class();
|
| + class_name = String::Handle(zone, cls.Name()).ToCString();
|
| } else {
|
| - class_name = UnresolvedClass::Handle(unresolved_class()).ToCString();
|
| + class_name = UnresolvedClass::Handle(zone, unresolved_class()).ToCString();
|
| }
|
| - if (type_arguments.IsNull()) {
|
| - return OS::SCreate(Thread::Current()->zone(),
|
| - "%sType: class '%s'", unresolved, class_name);
|
| + if (IsFunctionType()) {
|
| + const Function& sig_fun = Function::Handle(zone, signature());
|
| + const String& sig = IsFinalized() ?
|
| + String::Handle(zone, sig_fun.InstantiatedSignatureFrom(type_args,
|
| + kInternalName)) :
|
| + String::Handle(zone, sig_fun.Signature());
|
| + if (cls.IsClosureClass()) {
|
| + ASSERT(type_args.IsNull());
|
| + return OS::SCreate(zone, "%sFunction Type: %s",
|
| + unresolved, sig.ToCString());
|
| + }
|
| + return OS::SCreate(zone, "%s Function Type: %s (class: %s, args: %s)",
|
| + unresolved,
|
| + sig.ToCString(),
|
| + class_name,
|
| + args_cstr);
|
| + }
|
| + if (type_args.IsNull()) {
|
| + return OS::SCreate(zone, "%sType: class '%s'", unresolved, class_name);
|
| } else if (IsResolved() && IsFinalized() && IsRecursive()) {
|
| const intptr_t hash = Hash();
|
| - const char* args_cstr = TypeArguments::Handle(arguments()).ToCString();
|
| - return OS::SCreate(Thread::Current()->zone(),
|
| - "Type: (@%p H%" Px ") class '%s', args:[%s]",
|
| - raw(), hash, class_name, args_cstr);
|
| - } else {
|
| - const char* args_cstr = TypeArguments::Handle(arguments()).ToCString();
|
| - return OS::SCreate(Thread::Current()->zone(),
|
| - "%sType: class '%s', args:[%s]", unresolved, class_name, args_cstr);
|
| - }
|
| -}
|
| -
|
| -
|
| -void FunctionType::SetIsFinalized() const {
|
| - ASSERT(!IsFinalized());
|
| - if (IsInstantiated()) {
|
| - set_type_state(RawFunctionType::kFinalizedInstantiated);
|
| + return OS::SCreate(zone, "Type: (@%p H%" Px ") class '%s', args:[%s]",
|
| + raw(), hash, class_name, args_cstr);
|
| } else {
|
| - set_type_state(RawFunctionType::kFinalizedUninstantiated);
|
| - }
|
| -}
|
| -
|
| -
|
| -void FunctionType::ResetIsFinalized() const {
|
| - ASSERT(IsFinalized());
|
| - set_type_state(RawFunctionType::kBeingFinalized);
|
| - SetIsFinalized();
|
| -}
|
| -
|
| -
|
| -void FunctionType::SetIsBeingFinalized() const {
|
| - ASSERT(IsResolved() && !IsFinalized() && !IsBeingFinalized());
|
| - set_type_state(RawFunctionType::kBeingFinalized);
|
| -}
|
| -
|
| -
|
| -bool FunctionType::IsMalformed() const {
|
| - if (raw_ptr()->error_ == LanguageError::null()) {
|
| - return false;
|
| - }
|
| - const LanguageError& type_error = LanguageError::Handle(error());
|
| - return type_error.kind() == Report::kMalformedType;
|
| -}
|
| -
|
| -
|
| -bool FunctionType::IsMalbounded() const {
|
| - if (!Isolate::Current()->type_checks()) {
|
| - return false;
|
| + return OS::SCreate(zone, "%sType: class '%s', args:[%s]",
|
| + unresolved, class_name, args_cstr);
|
| }
|
| - if (raw_ptr()->error_ == LanguageError::null()) {
|
| - return false;
|
| - }
|
| - const LanguageError& type_error = LanguageError::Handle(error());
|
| - return type_error.kind() == Report::kMalboundedType;
|
| }
|
|
|
|
|
| -bool FunctionType::IsMalformedOrMalbounded() const {
|
| - if (raw_ptr()->error_ == LanguageError::null()) {
|
| - return false;
|
| - }
|
| - const LanguageError& type_error = LanguageError::Handle(error());
|
| - if (type_error.kind() == Report::kMalformedType) {
|
| +bool TypeRef::IsInstantiated(TrailPtr trail) const {
|
| + if (TestAndAddToTrail(&trail)) {
|
| return true;
|
| }
|
| - ASSERT(type_error.kind() == Report::kMalboundedType);
|
| - return Isolate::Current()->type_checks();
|
| -}
|
| -
|
| -
|
| -void FunctionType::set_error(const LanguageError& value) const {
|
| - StorePointer(&raw_ptr()->error_, value.raw());
|
| -}
|
| -
|
| -
|
| -void FunctionType::SetIsResolved() const {
|
| - ASSERT(!IsResolved());
|
| - set_type_state(RawFunctionType::kResolved);
|
| + return AbstractType::Handle(type()).IsInstantiated(trail);
|
| }
|
|
|
|
|
| -bool FunctionType::IsInstantiated(TrailPtr trail) const {
|
| - if (raw_ptr()->type_state_ == RawFunctionType::kFinalizedInstantiated) {
|
| +bool TypeRef::IsEquivalent(const Instance& other, TrailPtr trail) const {
|
| + if (raw() == other.raw()) {
|
| return true;
|
| }
|
| - if (raw_ptr()->type_state_ == RawFunctionType::kFinalizedUninstantiated) {
|
| + if (!other.IsAbstractType()) {
|
| return false;
|
| }
|
| - if (arguments() == TypeArguments::null()) {
|
| - return true;
|
| - }
|
| - const Class& scope_cls = Class::Handle(scope_class());
|
| - if (!scope_cls.IsGeneric()) {
|
| - ASSERT(scope_cls.IsClosureClass() || scope_cls.IsTypedefClass());
|
| - ASSERT(arguments() == TypeArguments::null());
|
| + if (TestAndAddBuddyToTrail(&trail, AbstractType::Cast(other))) {
|
| return true;
|
| }
|
| - const TypeArguments& type_arguments = TypeArguments::Handle(arguments());
|
| - const intptr_t num_type_args = scope_cls.NumTypeArguments();
|
| - const intptr_t num_type_params = scope_cls.NumTypeParameters();
|
| - // The vector may be longer than necessary. An empty vector is handled above.
|
| - ASSERT(type_arguments.Length() >= num_type_args);
|
| - return
|
| - (num_type_params == 0) ||
|
| - type_arguments.IsSubvectorInstantiated(num_type_args - num_type_params,
|
| - num_type_params);
|
| + return AbstractType::Handle(type()).IsEquivalent(other, trail);
|
| }
|
|
|
|
|
| -RawAbstractType* FunctionType::InstantiateFrom(
|
| - const TypeArguments& instantiator_type_arguments,
|
| - Error* bound_error,
|
| - TrailPtr instantiation_trail,
|
| - TrailPtr bound_trail,
|
| - Heap::Space space) const {
|
| - Zone* zone = Thread::Current()->zone();
|
| - ASSERT(IsFinalized() || IsBeingFinalized());
|
| - ASSERT(!IsInstantiated());
|
| - ASSERT(!IsMalformed()); // FunctionType cannot be malformed.
|
| - // Instantiating this type with its own type arguments as instantiator can
|
| - // occur during finalization and bounds checking. Return the type unchanged.
|
| - if (arguments() == instantiator_type_arguments.raw()) {
|
| - return raw();
|
| - }
|
| - // Note that the scope class has to be resolved at this time, but not
|
| - // necessarily finalized yet. We may be checking bounds at compile time or
|
| - // finalizing the type argument vector of a recursive type.
|
| - const Class& cls = Class::Handle(zone, scope_class());
|
| - TypeArguments& type_arguments = TypeArguments::Handle(zone, arguments());
|
| - ASSERT(type_arguments.Length() == cls.NumTypeArguments());
|
| - type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments,
|
| - bound_error,
|
| - instantiation_trail,
|
| - bound_trail,
|
| - space);
|
| - // This uninstantiated type is not modified, as it can be instantiated
|
| - // with different instantiators. Allocate a new instantiated version of it.
|
| - const FunctionType& instantiated_type = FunctionType::Handle(zone,
|
| - FunctionType::New(cls,
|
| - type_arguments,
|
| - Function::Handle(zone, signature()),
|
| - token_pos(),
|
| - space));
|
| - if (IsFinalized()) {
|
| - instantiated_type.SetIsFinalized();
|
| - } else {
|
| - instantiated_type.SetIsResolved();
|
| - }
|
| - // Canonicalization is not part of instantiation.
|
| - return instantiated_type.raw();
|
| -}
|
| -
|
| -
|
| -bool FunctionType::IsEquivalent(const Instance& other, TrailPtr trail) const {
|
| - ASSERT(!IsNull());
|
| - if (raw() == other.raw()) {
|
| - return true;
|
| - }
|
| - if (!other.IsFunctionType()) {
|
| - return false;
|
| - }
|
| - const FunctionType& other_type = FunctionType::Cast(other);
|
| - ASSERT(IsResolved() && other_type.IsResolved());
|
| - if (IsMalformed() || other_type.IsMalformed()) {
|
| - return false;
|
| - }
|
| - if (scope_class() != other_type.scope_class()) {
|
| - return false;
|
| - }
|
| - if ((arguments() == other_type.arguments()) &&
|
| - (signature() == other_type.signature())) {
|
| - return true;
|
| - }
|
| - if (!IsFinalized() || !other_type.IsFinalized()) {
|
| - return false;
|
| - }
|
| -
|
| - // We do not instantiate the types of the signature. This happens on demand
|
| - // at runtime during a type test.
|
| - // Therefore, equal function types must have equal type arguments.
|
| - Thread* thread = Thread::Current();
|
| - Zone* zone = thread->zone();
|
| - const TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
|
| - const TypeArguments& other_type_args = TypeArguments::Handle(
|
| - zone, other_type.arguments());
|
| - if (!type_args.Equals(other_type_args)) {
|
| - return false;
|
| - }
|
| -
|
| - // Type arguments are equal.
|
| - // Equal function types must have equal signature types and equal optional
|
| - // named arguments.
|
| - if (signature() == other_type.signature()) {
|
| - return true;
|
| - }
|
| - const Function& sig_fun = Function::Handle(zone, signature());
|
| - const Function& other_sig_fun = Function::Handle(
|
| - zone, other_type.signature());
|
| -
|
| - // Compare number of function parameters.
|
| - const intptr_t num_fixed_params = sig_fun.num_fixed_parameters();
|
| - const intptr_t other_num_fixed_params = other_sig_fun.num_fixed_parameters();
|
| - if (num_fixed_params != other_num_fixed_params) {
|
| - return false;
|
| - }
|
| - const intptr_t num_opt_pos_params = sig_fun.NumOptionalPositionalParameters();
|
| - const intptr_t other_num_opt_pos_params =
|
| - other_sig_fun.NumOptionalPositionalParameters();
|
| - if (num_opt_pos_params != other_num_opt_pos_params) {
|
| - return false;
|
| - }
|
| - const intptr_t num_opt_named_params = sig_fun.NumOptionalNamedParameters();
|
| - const intptr_t other_num_opt_named_params =
|
| - other_sig_fun.NumOptionalNamedParameters();
|
| - if (num_opt_named_params != other_num_opt_named_params) {
|
| - return false;
|
| - }
|
| - const intptr_t num_ignored_params = sig_fun.NumImplicitParameters();
|
| - const intptr_t other_num_ignored_params =
|
| - other_sig_fun.NumImplicitParameters();
|
| - if (num_ignored_params != other_num_ignored_params) {
|
| - return false;
|
| - }
|
| - AbstractType& param_type = Type::Handle(zone);
|
| - AbstractType& other_param_type = Type::Handle(zone);
|
| - // Check the result type.
|
| - param_type = sig_fun.result_type();
|
| - other_param_type = other_sig_fun.result_type();
|
| - if (!param_type.Equals(other_param_type)) {
|
| - return false;
|
| - }
|
| - // Check the types of all parameters.
|
| - const intptr_t num_params = sig_fun.NumParameters();
|
| - ASSERT(other_sig_fun.NumParameters() == num_params);
|
| - for (intptr_t i = 0; i < num_params; i++) {
|
| - param_type = sig_fun.ParameterTypeAt(i);
|
| - other_param_type = other_sig_fun.ParameterTypeAt(i);
|
| - if (!param_type.Equals(other_param_type)) {
|
| - return false;
|
| - }
|
| - }
|
| - // Check the names and types of optional named parameters.
|
| - if (num_opt_named_params == 0) {
|
| - return true;
|
| - }
|
| - for (intptr_t i = num_fixed_params; i < num_params; i++) {
|
| - if (sig_fun.ParameterNameAt(i) != other_sig_fun.ParameterNameAt(i)) {
|
| - return false;
|
| - }
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -
|
| -bool FunctionType::IsRecursive() const {
|
| - return TypeArguments::Handle(arguments()).IsRecursive();
|
| -}
|
| -
|
| -
|
| -RawAbstractType* FunctionType::CloneUnfinalized() const {
|
| - ASSERT(IsResolved());
|
| - if (IsFinalized()) {
|
| - return raw();
|
| - }
|
| - ASSERT(!IsMalformed()); // Malformed types are finalized.
|
| - ASSERT(!IsBeingFinalized()); // Cloning must occur prior to finalization.
|
| - TypeArguments& type_args = TypeArguments::Handle(arguments());
|
| - type_args = type_args.CloneUnfinalized();
|
| - const FunctionType& clone = FunctionType::Handle(
|
| - FunctionType::New(Class::Handle(scope_class()),
|
| - type_args,
|
| - Function::Handle(signature()),
|
| - token_pos()));
|
| - clone.SetIsResolved();
|
| - return clone.raw();
|
| -}
|
| -
|
| -
|
| -RawAbstractType* FunctionType::CloneUninstantiated(const Class& new_owner,
|
| - TrailPtr trail) const {
|
| - ASSERT(IsFinalized());
|
| - ASSERT(!IsMalformed());
|
| - if (IsInstantiated()) {
|
| - return raw();
|
| - }
|
| - // We may recursively encounter a type already being cloned, because we clone
|
| - // the upper bounds of its uninstantiated type arguments in the same pass.
|
| - FunctionType& clone = FunctionType::Handle();
|
| - clone ^= OnlyBuddyInTrail(trail);
|
| - if (!clone.IsNull()) {
|
| - return clone.raw();
|
| - }
|
| - clone = FunctionType::New(Class::Handle(scope_class()),
|
| - TypeArguments::Handle(),
|
| - Function::Handle(signature()),
|
| - token_pos());
|
| - TypeArguments& type_args = TypeArguments::Handle(arguments());
|
| - // Upper bounds of uninstantiated type arguments may form a cycle.
|
| - if (type_args.IsRecursive() || !type_args.IsInstantiated()) {
|
| - AddOnlyBuddyToTrail(&trail, clone);
|
| - }
|
| - type_args = type_args.CloneUninstantiated(new_owner, trail);
|
| - clone.set_arguments(type_args);
|
| - clone.SetIsFinalized();
|
| - return clone.raw();
|
| -}
|
| -
|
| -
|
| -RawAbstractType* FunctionType::Canonicalize(TrailPtr trail) const {
|
| - ASSERT(IsFinalized());
|
| - if (IsCanonical() || IsMalformed()) {
|
| - ASSERT(IsMalformed() || TypeArguments::Handle(arguments()).IsOld());
|
| - return this->raw();
|
| - }
|
| - Thread* thread = Thread::Current();
|
| - Zone* zone = thread->zone();
|
| - AbstractType& type = Type::Handle(zone);
|
| - const Class& scope_cls = Class::Handle(zone, type_class());
|
| - Array& canonical_types = Array::Handle(zone);
|
| - canonical_types ^= scope_cls.canonical_types();
|
| - if (canonical_types.IsNull()) {
|
| - canonical_types = empty_array().raw();
|
| - }
|
| - intptr_t length = canonical_types.Length();
|
| - // Linear search to see whether this type is already present in the
|
| - // list of canonicalized types.
|
| - // TODO(asiva): Try to re-factor this lookup code to make sharing
|
| - // easy between the 4 versions of this loop.
|
| - intptr_t index = 1; // Slot 0 is reserved for CanonicalType().
|
| - while (index < length) {
|
| - type ^= canonical_types.At(index);
|
| - if (type.IsNull()) {
|
| - break;
|
| - }
|
| - ASSERT(type.IsFinalized());
|
| - if (this->Equals(type)) {
|
| - ASSERT(type.IsCanonical());
|
| - return type.raw();
|
| - }
|
| - index++;
|
| - }
|
| - // The type was not found in the table. It is not canonical yet.
|
| -
|
| - // Canonicalize the type arguments.
|
| - TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
|
| - // In case the type is first canonicalized at runtime, its type argument
|
| - // vector may be longer than necessary. This is not an issue.
|
| - ASSERT(type_args.IsNull() ||
|
| - (type_args.Length() >= scope_cls.NumTypeArguments()));
|
| - type_args = type_args.Canonicalize(trail);
|
| - if (IsCanonical()) {
|
| - // Canonicalizing type_args canonicalized this type as a side effect.
|
| - ASSERT(IsRecursive());
|
| - // Cycles via typedefs are detected and disallowed, but a function type can
|
| - // be recursive due to a cycle in its type arguments.
|
| - return this->raw();
|
| - }
|
| - set_arguments(type_args);
|
| -
|
| - // Replace the actual function by a signature function.
|
| - const Function& fun = Function::Handle(zone, signature());
|
| - if (!fun.IsSignatureFunction()) {
|
| - Function& sig_fun = Function::Handle(zone,
|
| - Function::NewSignatureFunction(scope_cls, TokenPosition::kNoSource));
|
| - type = fun.result_type();
|
| - type = type.Canonicalize(trail);
|
| - sig_fun.set_result_type(type);
|
| - const intptr_t num_params = fun.NumParameters();
|
| - sig_fun.set_num_fixed_parameters(fun.num_fixed_parameters());
|
| - sig_fun.SetNumOptionalParameters(fun.NumOptionalParameters(),
|
| - fun.HasOptionalPositionalParameters());
|
| - sig_fun.set_parameter_types(Array::Handle(Array::New(num_params,
|
| - Heap::kOld)));
|
| - for (intptr_t i = 0; i < num_params; i++) {
|
| - type = fun.ParameterTypeAt(i);
|
| - type = type.Canonicalize(trail);
|
| - sig_fun.SetParameterTypeAt(i, type);
|
| - }
|
| - sig_fun.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
|
| - set_signature(sig_fun);
|
| - }
|
| - ASSERT(type_args.IsNull() || type_args.IsOld());
|
| -
|
| - return scope_cls.LookupOrAddCanonicalType(*this, index);
|
| -}
|
| -
|
| -
|
| -RawString* FunctionType::EnumerateURIs() const {
|
| - Zone* zone = Thread::Current()->zone();
|
| - // The scope class and type arguments do not appear explicitly in the user
|
| - // visible name. The type arguments were used to instantiate the function type
|
| - // prior to this call.
|
| - const Function& sig_fun = Function::Handle(zone, signature());
|
| - AbstractType& type = AbstractType::Handle(zone);
|
| - const intptr_t num_params = sig_fun.NumParameters();
|
| - GrowableHandlePtrArray<const String> pieces(zone, num_params + 1);
|
| - for (intptr_t i = 0; i < num_params; i++) {
|
| - type = sig_fun.ParameterTypeAt(i);
|
| - pieces.Add(String::Handle(zone, type.EnumerateURIs()));
|
| - }
|
| - // Handle result type last, since it appears last in the user visible name.
|
| - type = sig_fun.result_type();
|
| - pieces.Add(String::Handle(zone, type.EnumerateURIs()));
|
| - return Symbols::FromConcatAll(pieces);
|
| -}
|
| -
|
| -
|
| -intptr_t FunctionType::Hash() const {
|
| - ASSERT(IsFinalized());
|
| - uint32_t result = 1;
|
| - if (IsMalformed()) return result;
|
| - result = CombineHashes(result, Class::Handle(scope_class()).id());
|
| - result = CombineHashes(result, TypeArguments::Handle(arguments()).Hash());
|
| - const Function& sig_fun = Function::Handle(signature());
|
| - AbstractType& type = AbstractType::Handle(sig_fun.result_type());
|
| - result = CombineHashes(result, type.Hash());
|
| - result = CombineHashes(result, sig_fun.NumOptionalPositionalParameters());
|
| - const intptr_t num_params = sig_fun.NumParameters();
|
| - for (intptr_t i = 0; i < num_params; i++) {
|
| - type = sig_fun.ParameterTypeAt(i);
|
| - result = CombineHashes(result, type.Hash());
|
| - }
|
| - if (sig_fun.NumOptionalNamedParameters() > 0) {
|
| - String& param_name = String::Handle();
|
| - for (intptr_t i = sig_fun.num_fixed_parameters(); i < num_params; i++) {
|
| - param_name = sig_fun.ParameterNameAt(i);
|
| - result = CombineHashes(result, param_name.Hash());
|
| - }
|
| - }
|
| - return FinalizeHash(result);
|
| -}
|
| -
|
| -
|
| -void FunctionType::set_scope_class(const Class& value) const {
|
| - ASSERT(!value.IsNull());
|
| - StorePointer(&raw_ptr()->scope_class_, value.raw());
|
| -}
|
| -
|
| -
|
| -void FunctionType::set_arguments(const TypeArguments& value) const {
|
| - ASSERT(!IsCanonical());
|
| - StorePointer(&raw_ptr()->arguments_, value.raw());
|
| -}
|
| -
|
| -
|
| -void FunctionType::set_signature(const Function& value) const {
|
| - StorePointer(&raw_ptr()->signature_, value.raw());
|
| -}
|
| -
|
| -
|
| -RawFunctionType* FunctionType::New(Heap::Space space) {
|
| - RawObject* raw = Object::Allocate(FunctionType::kClassId,
|
| - FunctionType::InstanceSize(),
|
| - space);
|
| - return reinterpret_cast<RawFunctionType*>(raw);
|
| -}
|
| -
|
| -
|
| -RawFunctionType* FunctionType::New(const Class& clazz,
|
| - const TypeArguments& arguments,
|
| - const Function& signature,
|
| - TokenPosition token_pos,
|
| - Heap::Space space) {
|
| - const FunctionType& result = FunctionType::Handle(FunctionType::New(space));
|
| - result.set_scope_class(clazz);
|
| - result.set_arguments(arguments);
|
| - result.set_signature(signature);
|
| - result.set_token_pos(token_pos);
|
| - result.StoreNonPointer(&result.raw_ptr()->type_state_,
|
| - RawFunctionType::kAllocated);
|
| - return result.raw();
|
| -}
|
| -
|
| -
|
| -void FunctionType::set_token_pos(TokenPosition token_pos) const {
|
| - ASSERT(!token_pos.IsClassifying());
|
| - StoreNonPointer(&raw_ptr()->token_pos_, token_pos);
|
| -}
|
| -
|
| -
|
| -void FunctionType::set_type_state(int8_t state) const {
|
| - ASSERT((state >= RawFunctionType::kAllocated) &&
|
| - (state <= RawFunctionType::kFinalizedUninstantiated));
|
| - StoreNonPointer(&raw_ptr()->type_state_, state);
|
| -}
|
| -
|
| -
|
| -const char* FunctionType::ToCString() const {
|
| - const char* unresolved = IsResolved() ? "" : "Unresolved ";
|
| - const Class& scope_cls = Class::Handle(scope_class());
|
| - const TypeArguments& type_arguments = TypeArguments::Handle(arguments());
|
| - const Function& signature_function = Function::Handle(signature());
|
| - const String& signature_string = IsFinalized() ?
|
| - String::Handle(
|
| - signature_function.InstantiatedSignatureFrom(type_arguments,
|
| - kInternalName)) :
|
| - String::Handle(signature_function.Signature());
|
| - if (scope_cls.IsClosureClass()) {
|
| - ASSERT(arguments() == TypeArguments::null());
|
| - return OS::SCreate(
|
| - Thread::Current()->zone(),
|
| - "%sFunctionType: %s", unresolved, signature_string.ToCString());
|
| - }
|
| - const char* class_name = String::Handle(scope_cls.Name()).ToCString();
|
| - const char* args_cstr =
|
| - type_arguments.IsNull() ? "null" : type_arguments.ToCString();
|
| - return OS::SCreate(
|
| - Thread::Current()->zone(),
|
| - "%s FunctionType: %s (scope_cls: %s, args: %s)",
|
| - unresolved,
|
| - signature_string.ToCString(),
|
| - class_name,
|
| - args_cstr);
|
| -}
|
| -
|
| -
|
| -bool TypeRef::IsInstantiated(TrailPtr trail) const {
|
| - if (TestAndAddToTrail(&trail)) {
|
| - return true;
|
| - }
|
| - return AbstractType::Handle(type()).IsInstantiated(trail);
|
| -}
|
| -
|
| -
|
| -bool TypeRef::IsEquivalent(const Instance& other, TrailPtr trail) const {
|
| - if (raw() == other.raw()) {
|
| - return true;
|
| - }
|
| - if (!other.IsAbstractType()) {
|
| - return false;
|
| - }
|
| - if (TestAndAddBuddyToTrail(&trail, AbstractType::Cast(other))) {
|
| - return true;
|
| - }
|
| - return AbstractType::Handle(type()).IsEquivalent(other, trail);
|
| -}
|
| -
|
| -
|
| -RawTypeRef* TypeRef::InstantiateFrom(
|
| +RawTypeRef* TypeRef::InstantiateFrom(
|
| const TypeArguments& instantiator_type_arguments,
|
| Error* bound_error,
|
| TrailPtr instantiation_trail,
|
| @@ -17289,9 +17056,12 @@ RawAbstractType* BoundedType::CloneUnfinalized() const {
|
| if (IsFinalized()) {
|
| return raw();
|
| }
|
| - AbstractType& bounded_type = AbstractType::Handle(type());
|
| -
|
| - bounded_type = bounded_type.CloneUnfinalized();
|
| + const AbstractType& bounded_type = AbstractType::Handle(type());
|
| + const AbstractType& bounded_type_clone =
|
| + AbstractType::Handle(bounded_type.CloneUnfinalized());
|
| + if (bounded_type_clone.raw() == bounded_type.raw()) {
|
| + return raw();
|
| + }
|
| // No need to clone bound or type parameter, as they are not part of the
|
| // finalization state of this bounded type.
|
| return BoundedType::New(bounded_type,
|
|
|