Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(728)

Unified Diff: runtime/vm/object.cc

Issue 2979763002: [VM generic function types] Properly set the scope function after parsing a (Closed)
Patch Set: address comments, move new test from language to language_2, sync Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/object.cc
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 5a3eecc28299e2894c55eb3b6c847e186bc6798f..3a45edf9bf946230095921753dafe12b4d63331c 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -4583,6 +4583,18 @@ bool TypeArguments::IsRecursive() const {
return false;
}
+void TypeArguments::SetScopeFunction(const Function& function) const {
+ if (IsNull()) return;
+ const intptr_t num_types = Length();
+ AbstractType& type = AbstractType::Handle();
+ for (intptr_t i = 0; i < num_types; i++) {
+ type = TypeAt(i);
+ if (!type.IsNull()) {
+ type.SetScopeFunction(function);
+ }
+ }
+}
+
bool TypeArguments::IsDynamicTypes(bool raw_instantiated,
intptr_t from_index,
intptr_t len) const {
@@ -5479,43 +5491,6 @@ RawType* Function::ExistingSignatureType() const {
}
}
-RawFunction* Function::CanonicalSignatureFunction(TrailPtr trail) const {
- ASSERT(!IsSignatureFunction());
- Zone* zone = Thread::Current()->zone();
- Function& parent = Function::Handle(zone, parent_function());
- if (!parent.IsNull() && !parent.IsSignatureFunction()) {
- // Make sure the parent function is also a signature function.
- parent = parent.CanonicalSignatureFunction(trail);
- }
- const Class& owner = Class::Handle(zone, Owner());
- const Function& sig_fun = Function::Handle(
- zone,
- Function::NewSignatureFunction(owner, parent, TokenPosition::kNoSource));
- // In case of a generic function, the function type parameters in the
- // signature will still refer to the original function. This should not
- // be a problem, since once finalized the indices will be identical.
- sig_fun.set_type_parameters(TypeArguments::Handle(zone, type_parameters()));
- ASSERT(HasGenericParent() == sig_fun.HasGenericParent());
- ASSERT(IsGeneric() == sig_fun.IsGeneric());
- AbstractType& type = AbstractType::Handle(zone);
- type = result_type();
- type = type.Canonicalize(trail);
- sig_fun.set_result_type(type);
- const intptr_t num_params = NumParameters();
- sig_fun.set_num_fixed_parameters(num_fixed_parameters());
- sig_fun.SetNumOptionalParameters(NumOptionalParameters(),
- HasOptionalPositionalParameters());
- sig_fun.set_parameter_types(
- Array::Handle(Array::New(num_params, Heap::kOld)));
- for (intptr_t i = 0; i < num_params; i++) {
- type = ParameterTypeAt(i);
- type = type.Canonicalize(trail);
- sig_fun.SetParameterTypeAt(i, type);
- }
- sig_fun.set_parameter_names(Array::Handle(zone, parameter_names()));
- return sig_fun.raw();
-}
-
RawType* Function::SignatureType() const {
Type& type = Type::Handle(ExistingSignatureType());
if (type.IsNull()) {
@@ -5769,13 +5744,6 @@ void Function::set_native_name(const String& value) const {
void Function::set_result_type(const AbstractType& value) const {
ASSERT(!value.IsNull());
StorePointer(&raw_ptr()->result_type_, value.raw());
- if (value.IsFunctionType()) {
- // The function result type may refer to this function's type parameters.
- // Change its parent function.
- const Function& result_signature_function =
- Function::Handle(Type::Cast(value).signature());
- result_signature_function.set_parent_function(*this);
- }
}
RawAbstractType* Function::ParameterTypeAt(intptr_t index) const {
@@ -5836,11 +5804,24 @@ intptr_t Function::NumParentTypeParameters() const {
intptr_t num_parent_type_params = 0;
while (!parent.IsNull()) {
num_parent_type_params += parent.NumTypeParameters(thread);
+ if (parent.IsImplicitClosureFunction()) break;
parent ^= parent.parent_function();
}
return num_parent_type_params;
}
+void Function::PrintSignatureTypes() const {
+ Function& sig_fun = Function::Handle(raw());
+ Type& sig_type = Type::Handle();
+ while (!sig_fun.IsNull()) {
+ sig_type = sig_fun.SignatureType();
+ THR_Print("%s%s\n",
+ sig_fun.IsImplicitClosureFunction() ? "implicit closure: " : "",
+ sig_type.ToCString());
+ sig_fun ^= sig_fun.parent_function();
+ }
+}
+
RawTypeParameter* Function::LookupTypeParameter(
const String& type_name,
intptr_t* function_level) const {
@@ -6297,6 +6278,8 @@ RawFunction* Function::InstantiateSignatureFrom(
Heap::Space space) const {
Zone* zone = Thread::Current()->zone();
const Object& owner = Object::Handle(zone, RawOwner());
+ // Note that parent pointers in newly instantiated signatures still points to
+ // the original uninstantiated parent signatures. That is not a problem.
const Function& parent = Function::Handle(zone, parent_function());
ASSERT(!HasInstantiatedSignature());
Function& sig = Function::Handle(
@@ -6971,12 +6954,22 @@ bool Function::HasInstantiatedSignature(Genericity genericity,
intptr_t num_free_fun_type_params,
TrailPtr trail) const {
if (genericity != kCurrentClass) {
- // We only consider the function type parameters declared by the parents of
- // this signature function.
- const int num_parent_type_params = NumParentTypeParameters();
- if (num_parent_type_params < num_free_fun_type_params) {
- num_free_fun_type_params = num_parent_type_params;
+ // A generic typedef may declare a non-generic function type and get
+ // instantiated with unrelated function type parameters. In that case, its
+ // signature is still uninstantiated, because these type parameters are
+ // free (they are not declared by the typedef).
+ // For that reason, we only adjust num_free_fun_type_params if this
+ // signature is generic or has a generic parent.
+ if (IsGeneric() || HasGenericParent()) {
+ // We only consider the function type parameters declared by the parents
+ // of this signature function as free.
+ const int num_parent_type_params = NumParentTypeParameters();
+ if (num_parent_type_params < num_free_fun_type_params) {
+ num_free_fun_type_params = num_parent_type_params;
+ }
}
+ // TODO(regis): Should we check the owners of the function type parameters
+ // in addition to their indexes to decide if they are free or not?
}
AbstractType& type = AbstractType::Handle(result_type());
if (!type.IsInstantiated(genericity, num_free_fun_type_params, trail)) {
@@ -15525,6 +15518,11 @@ bool AbstractType::IsRecursive() const {
return false;
}
+void AbstractType::SetScopeFunction(const Function& function) const {
+ // AbstractType is an abstract class.
+ UNREACHABLE();
+}
+
RawAbstractType* AbstractType::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
@@ -15926,7 +15924,6 @@ bool AbstractType::TypeTest(TypeTestKind test_kind,
if (type_param.Equals(other_type_param)) {
return true;
}
- // TODO(regis): Should we update TypeParameter::IsEquivalent() instead?
if (type_param.IsFunctionTypeParameter() &&
other_type_param.IsFunctionTypeParameter() &&
type_param.IsFinalized() && other_type_param.IsFinalized()) {
@@ -16509,6 +16506,16 @@ bool Type::IsRecursive() const {
return TypeArguments::Handle(arguments()).IsRecursive();
}
+void Type::SetScopeFunction(const Function& function) const {
+ TypeArguments::Handle(arguments()).SetScopeFunction(function);
+ if (IsFunctionType()) {
+ const Function& sig_fun = Function::Handle(signature());
+ sig_fun.set_parent_function(function);
+ // No need to traverse result type and parameter types (and bounds, in case
+ // sig_fun is generic), since they have sig_fun as scope function.
+ }
+}
+
RawAbstractType* Type::CloneUnfinalized() const {
ASSERT(IsResolved());
if (IsFinalized()) {
@@ -16747,19 +16754,11 @@ RawAbstractType* Type::Canonicalize(TrailPtr trail) const {
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()) {
- Function& sig_fun = Function::Handle(zone, signature());
- if (!sig_fun.IsSignatureFunction()) {
- sig_fun = sig_fun.CanonicalSignatureFunction(trail);
- set_signature(sig_fun);
- // Note that the signature type of the signature function may be
- // different than the type being canonicalized.
- // Consider F<int> being canonicalized, with F being a typedef and F<T>
- // being its signature type.
- }
- }
+ // In case of a function type, the signature has already been canonicalized
+ // when finalizing the type and passing kCanonicalize as finalization.
+ // Therefore, we do not canonicalize the signature here, which would have no
+ // effect on selecting the canonical type anyway, because the function
+ // object is not replaced when canonicalizing the signature.
// Check to see if the type got added to canonical list as part of the
// type arguments canonicalization.
@@ -16993,6 +16992,12 @@ bool TypeRef::IsEquivalent(const Instance& other, TrailPtr trail) const {
return !ref_type.IsNull() && ref_type.IsEquivalent(other, trail);
}
+void TypeRef::SetScopeFunction(const Function& function) const {
+ // TypeRefs are created during finalization, when scope functions have
+ // already been adjusted.
+ UNREACHABLE();
+}
+
RawTypeRef* TypeRef::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
const TypeArguments& function_type_arguments,
@@ -17516,6 +17521,11 @@ bool BoundedType::IsRecursive() const {
return AbstractType::Handle(type()).IsRecursive();
}
+void BoundedType::SetScopeFunction(const Function& function) const {
+ AbstractType::Handle(type()).SetScopeFunction(function);
+ AbstractType::Handle(bound()).SetScopeFunction(function);
+}
+
void BoundedType::set_type(const AbstractType& value) const {
ASSERT(value.IsFinalized() || value.IsBeingFinalized() ||
value.IsTypeParameter());
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698