Make finalization of recursive function types more robust, especially since

the Kernel frontend may omit the information that a function type is a typedef.
Re-enable several previously failing tests for dartk.

R=asiva@google.com

Review-Url: https://codereview.chromium.org/2806893002 .
This commit is contained in:
Regis Crelier 2017-04-10 11:06:10 -07:00
parent d75edfb408
commit 8ca244ba27
3 changed files with 66 additions and 70 deletions

View file

@ -815,19 +815,8 @@ intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
}
}
// Self referencing types may get finalized indirectly.
if (!type.IsFinalized()) {
ASSERT(full_arguments.IsNull() ||
!full_arguments.IsRaw(0, num_type_arguments));
if (FLAG_trace_type_finalization) {
THR_Print("Marking type '%s' as finalized for class '%s'\n",
String::Handle(zone, type.Name()).ToCString(),
String::Handle(zone, cls.Name()).ToCString());
}
// Mark the type as finalized.
type.SetIsFinalized();
// Do not yet remove the type from the pending_types array.
}
ASSERT(full_arguments.IsNull() ||
!full_arguments.IsRaw(0, num_type_arguments));
return full_arguments.IsNull() ? 0 : full_arguments.Length();
}
@ -1225,6 +1214,57 @@ RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls,
const intptr_t num_expanded_type_arguments =
ExpandAndFinalizeTypeArguments(cls, type, pending_types);
// Self referencing types may get finalized indirectly.
if (!type.IsFinalized()) {
// If the type is a function type, we also need to finalize the types in its
// signature, i.e. finalize the result type and parameter types of the
// signature function of this function type.
// We do this after marking this type as finalized in order to allow a
// typedef function type to refer to itself via its parameter types and
// result type.
if (type.IsFunctionType()) {
const Type& fun_type = Type::Cast(type);
const Class& scope_class = Class::Handle(zone, fun_type.type_class());
if (scope_class.IsTypedefClass()) {
Function& signature =
Function::Handle(zone, scope_class.signature_function());
if (!scope_class.is_type_finalized()) {
FinalizeSignature(scope_class, signature);
}
// If the function type is a generic typedef, instantiate its signature
// from its type arguments.
// Example: typedef T F<T>(T x) has uninstantiated signature (T x) => T.
// The instantiated signature of F(int) becomes (int x) => int.
// Note that after this step, the signature of the function type is not
// identical to the canonical signature of the typedef class anymore.
if (scope_class.IsGeneric() && !signature.HasInstantiatedSignature()) {
const TypeArguments& type_args =
TypeArguments::Handle(zone, fun_type.arguments());
if (FLAG_trace_type_finalization) {
THR_Print("Instantiating signature '%s' of typedef '%s'\n",
String::Handle(zone, signature.Signature()).ToCString(),
String::Handle(zone, fun_type.Name()).ToCString());
}
signature = signature.InstantiateSignatureFrom(type_args, Heap::kOld);
// Note that if type_args contains type parameters, signature is still
// uninstantiated here (typedef type parameters were substituted in
// the signature with typedef type arguments).
}
fun_type.set_signature(signature);
} else {
FinalizeSignature(cls, Function::Handle(zone, fun_type.signature()));
}
}
if (FLAG_trace_type_finalization) {
THR_Print("Marking type '%s' as finalized for class '%s'\n",
String::Handle(zone, type.Name()).ToCString(),
String::Handle(zone, cls.Name()).ToCString());
}
// Mark the type as finalized.
type.SetIsFinalized();
}
// If we are done finalizing a graph of mutually recursive types, check their
// bounds.
if (is_root_type) {
@ -1236,52 +1276,6 @@ RawAbstractType* ClassFinalizer::FinalizeType(const Class& cls,
}
}
// If the type is a function type, we also need to finalize the types in its
// signature, i.e. finalize the result type and parameter types of the
// signature function of this function type.
// We do this after marking this type as finalized in order to allow a
// typedef function type to refer to itself via its parameter types and
// result type.
if (type.IsFunctionType()) {
ASSERT(!type.IsBeingFinalized());
const Type& fun_type = Type::Cast(type);
const Class& scope_class = Class::Handle(zone, fun_type.type_class());
if (scope_class.IsTypedefClass()) {
Function& signature =
Function::Handle(zone, scope_class.signature_function());
if (!scope_class.is_type_finalized()) {
FinalizeSignature(scope_class, signature);
}
// If the function type is a generic typedef, instantiate its signature
// from its type arguments.
// Example: typedef T F<T>(T x) has uninstantiated signature (T x) => T.
// The instantiated signature of F(int) becomes (int x) => int.
// Note that after this step, the signature of the function type is not
// identical to the canonical signature of the typedef class anymore.
if (scope_class.IsGeneric() && !signature.HasInstantiatedSignature()) {
const TypeArguments& type_args =
TypeArguments::Handle(zone, fun_type.arguments());
if (FLAG_trace_type_finalization) {
THR_Print("Instantiating signature '%s' of typedef '%s'\n",
String::Handle(zone, signature.Signature()).ToCString(),
String::Handle(zone, fun_type.Name()).ToCString());
}
signature = signature.InstantiateSignatureFrom(type_args, Heap::kOld);
// Note that if type_args contains type parameters, signature is still
// uninstantiated here (typedef type parameters were substituted in the
// signature with typedef type arguments).
}
fun_type.set_signature(signature);
// The type was already marked as finalized and uninstantiated in
// ExpandAndFinalizeTypeArguments above when its signature was not
// instantiated yet. Check again by calling ResetIsFinalized().
fun_type.ResetIsFinalized();
} else {
const Function& signature = Function::Handle(zone, fun_type.signature());
FinalizeSignature(cls, signature);
}
}
if (FLAG_trace_type_finalization) {
THR_Print("Done finalizing type '%s' with %" Pd " type args: %s\n",
String::Handle(zone, type.Name()).ToCString(),

View file

@ -16875,6 +16875,12 @@ bool Type::IsInstantiated(Genericity genericity, TrailPtr trail) const {
if (HasResolvedTypeClass()) {
const Class& cls = Class::Handle(type_class());
len = cls.NumTypeParameters(); // Check the type parameters only.
if (len > num_type_args) {
// This type has the wrong number of arguments and is not finalized yet.
// Type arguments are reset to null when finalizing such a type.
ASSERT(!IsFinalized());
len = num_type_args;
}
}
return (len == 0) ||
args.IsSubvectorInstantiated(num_type_args - len, len, genericity,
@ -16921,10 +16927,12 @@ RawAbstractType* Type::InstantiateFrom(
const LanguageError& bound_error = LanguageError::Handle(zone, error());
instantiated_type.set_error(bound_error);
}
// If this type is a function type, instantiate its signature.
// For a function type, possibly instantiate and set its signature.
if (!sig_fun.IsNull()) {
// If we are finalizing a typedef, do not yet instantiate its signature.
// Other function types should never be instantiated while unfinalized.
// If we are finalizing a typedef, do not yet instantiate its signature,
// since it gets instantiated just before the type is marked as finalized.
// Other function types should never get instantiated while unfinalized,
// even while checking bounds of recursive types.
if (IsFinalized()) {
// A generic typedef may actually declare an instantiated signature.
if (!sig_fun.HasInstantiatedSignature()) {
@ -16932,7 +16940,8 @@ RawAbstractType* Type::InstantiateFrom(
space);
}
} else {
ASSERT(cls.IsTypedefClass());
// The Kernel frontend does not keep the information that a function type
// is a typedef, so we cannot assert that cls.IsTypedefClass().
}
instantiated_type.set_signature(sig_fun);
}

View file

@ -88,11 +88,6 @@ cyclic_constructor_test/01: MissingCompileTimeError
cyclic_type_test/00: RuntimeError
cyclic_type_test/01: RuntimeError
cyclic_type_test/03: RuntimeError
cyclic_type_variable_test/01: Crash
cyclic_type_variable_test/02: Crash
cyclic_type_variable_test/03: Crash
cyclic_type_variable_test/04: Crash
cyclic_type_variable_test/none: Crash
cyclic_typedef_test/01: MissingCompileTimeError
cyclic_typedef_test/02: MissingCompileTimeError
cyclic_typedef_test/03: MissingCompileTimeError
@ -406,7 +401,6 @@ vm/optimized_stacktrace_test: Skip # Issue 28788
[ $compiler == dartk && $mode == debug ]
constructor_duplicate_initializers_test/03: Crash
deopt_inlined_function_lazy_test: Skip
function_malformed_result_type_test: Crash
hello_dart_test: Crash # error: expected: cls.is_type_finalized()
not_enough_positional_arguments_test/02: Crash # Dartk Issue 28301
not_enough_positional_arguments_test/05: Crash # Dartk Issue 28301
@ -419,7 +413,6 @@ ref_before_declaration_test/05: Crash
ref_before_declaration_test/06: Crash
ref_before_declaration_test/07: Crash
ref_before_declaration_test/none: Crash
regress_29025_test: Crash
try_catch_syntax_test/05: Crash
vm/lazy_deopt_vm_test: Crash