Index: runtime/vm/class_finalizer.cc |
=================================================================== |
--- runtime/vm/class_finalizer.cc (revision 25651) |
+++ runtime/vm/class_finalizer.cc (working copy) |
@@ -347,7 +347,6 @@ |
Error::Handle(), // No previous error. |
cls, |
factory.token_pos(), |
- kResolveTypeParameters, // No compile-time error. |
"factory may not redirect to 'dynamic'"); |
factory.SetRedirectionType(type); |
ASSERT(factory.RedirectionTarget() == Function::null()); |
@@ -375,7 +374,6 @@ |
Error::Handle(), // No previous error. |
cls, |
factory.token_pos(), |
- kResolveTypeParameters, // No compile-time error. |
"class '%s' has no constructor or factory named '%s'", |
target_class_name.ToCString(), |
user_visible_target_name.ToCString()); |
@@ -390,7 +388,6 @@ |
Error::Handle(), // No previous error. |
cls, |
factory.token_pos(), |
- kResolveTypeParameters, // No compile-time error. |
"constructor '%s' has incompatible parameters with " |
"redirecting factory '%s'", |
String::Handle(target.name()).ToCString(), |
@@ -437,8 +434,7 @@ |
if (malformed_error.IsNull()) { |
target_type ^= FinalizeType(cls, target_type, kCanonicalize); |
} else { |
- FinalizeMalformedType(malformed_error, |
- cls, target_type, kFinalize, |
+ FinalizeMalformedType(malformed_error, cls, target_type, |
"cannot resolve redirecting factory"); |
target_target = Function::null(); |
} |
@@ -453,9 +449,6 @@ |
const AbstractType& type, |
FinalizationKind finalization) { |
if (type.IsResolved() || type.IsFinalized()) { |
- if ((finalization == kCanonicalizeWellFormed) && type.IsMalformed()) { |
- ReportError(Error::Handle(type.malformed_error())); |
- } |
return; |
} |
if (FLAG_trace_type_finalization) { |
@@ -479,17 +472,27 @@ |
// Replace unresolved class with resolved type class. |
const Type& parameterized_type = Type::Cast(type); |
- if (!type_class.IsNull()) { |
- parameterized_type.set_type_class(type_class); |
- } else { |
- // The type class could not be resolved. The type is malformed. |
- FinalizeMalformedType(ambiguous_error, // May be null. |
- cls, parameterized_type, finalization, |
- "cannot resolve class name '%s' from '%s'", |
- String::Handle(unresolved_class.Name()).ToCString(), |
- String::Handle(cls.Name()).ToCString()); |
+ if (type_class.IsNull()) { |
+ if ((finalization == kCanonicalizeWellFormed) || |
+ FLAG_error_on_malformed_type) { |
+ // The type class could not be resolved. The type is malformed. |
+ FinalizeMalformedType( |
+ ambiguous_error, // May be null. |
+ cls, |
+ parameterized_type, |
+ "cannot resolve class '%s' from '%s'", |
+ String::Handle(unresolved_class.Name()).ToCString(), |
+ String::Handle(cls.Name()).ToCString()); |
+ } else { |
+ // Map the malformed type to dynamic and ignore type arguments. |
+ parameterized_type.set_type_class(Class::Handle( |
+ Object::dynamic_class())); |
+ parameterized_type.set_arguments( |
+ Object::null_abstract_type_arguments()); |
+ } |
return; |
} |
+ parameterized_type.set_type_class(type_class); |
} |
// Resolve type arguments, if any. |
@@ -708,14 +711,8 @@ |
if (type.IsFinalized()) { |
// Ensure type is canonical if canonicalization is requested, unless type is |
// malformed. |
- if (finalization >= kCanonicalize) { |
- if (type.IsMalformed()) { |
- if (finalization == kCanonicalizeWellFormed) { |
- ReportError(Error::Handle(type.malformed_error())); |
- } |
- } else { |
- return type.Canonicalize(); |
- } |
+ if ((finalization >= kCanonicalize) && !type.IsMalformed()) { |
+ return type.Canonicalize(); |
} |
return type.raw(); |
} |
@@ -749,15 +746,8 @@ |
// At this point, we can only have a parameterized_type. |
const Type& parameterized_type = Type::Cast(type); |
- if (parameterized_type.IsBeingFinalized()) { |
- // Self reference detected. The type is malformed. |
- FinalizeMalformedType( |
- Error::Handle(), // No previous error. |
- cls, parameterized_type, finalization, |
- "type '%s' illegally refers to itself", |
- String::Handle(parameterized_type.UserVisibleName()).ToCString()); |
- return parameterized_type.raw(); |
- } |
+ // Types illegally referring to themselves should have been detected earlier. |
+ ASSERT(!parameterized_type.IsBeingFinalized()); |
// Mark type as being finalized in order to detect illegal self reference. |
parameterized_type.set_is_being_finalized(); |
@@ -784,19 +774,8 @@ |
type_argument = arguments.TypeAt(i); |
type_argument = FinalizeType(cls, type_argument, finalization); |
if (type_argument.IsMalformed()) { |
- // In production mode, malformed type arguments are mapped to dynamic. |
- // In checked mode, a type with malformed type arguments is malformed. |
- if (FLAG_enable_type_checks || FLAG_error_on_malformed_type) { |
- const Error& error = Error::Handle(type_argument.malformed_error()); |
- const String& type_name = |
- String::Handle(parameterized_type.UserVisibleName()); |
- FinalizeMalformedType(error, cls, parameterized_type, finalization, |
- "type '%s' has malformed type argument", |
- type_name.ToCString()); |
- return parameterized_type.raw(); |
- } else { |
- type_argument = Type::DynamicType(); |
- } |
+ // Malformed type arguments are mapped to dynamic. |
+ type_argument = Type::DynamicType(); |
} |
arguments.SetTypeAt(i, type_argument); |
} |
@@ -813,20 +792,17 @@ |
// However, type parameter bounds are checked below, even for a raw type. |
if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) { |
// Wrong number of type arguments. The type is malformed. |
- if (finalization >= kCanonicalizeExpression) { |
+ if (FLAG_error_on_malformed_type) { |
const Script& script = Script::Handle(cls.script()); |
- const String& type_name = |
- String::Handle(parameterized_type.UserVisibleName()); |
+ const String& type_class_name = String::Handle(type_class.Name()); |
ReportError(script, parameterized_type.token_pos(), |
- "wrong number of type arguments in type '%s'", |
- type_name.ToCString()); |
+ "wrong number of type arguments for class '%s'", |
+ type_class_name.ToCString()); |
} |
- FinalizeMalformedType( |
- Error::Handle(), // No previous error. |
- cls, parameterized_type, finalization, |
- "wrong number of type arguments in type '%s'", |
- String::Handle(parameterized_type.UserVisibleName()).ToCString()); |
- return parameterized_type.raw(); |
+ // Make the type raw and continue without reporting any error. |
+ // A static warning should have been reported. |
+ arguments = AbstractTypeArguments::null(); |
+ parameterized_type.set_arguments(arguments); |
} |
// The full type argument vector consists of the type arguments of the |
// super types of type_class, which may be initialized from the parsed |
@@ -908,17 +884,12 @@ |
// The malformed bound will be ignored in production mode. |
if (!bound_error.IsNull()) { |
// No compile-time error during finalization. |
- FinalizationKind bound_finalization = kResolveTypeParameters; |
- if (FLAG_enable_type_checks || FLAG_error_on_malformed_type) { |
- bound_finalization = finalization; |
- } |
const String& parameterized_type_name = String::Handle( |
parameterized_type.UserVisibleName()); |
const Type& malformed_bound = Type::Handle( |
NewFinalizedMalformedType(bound_error, |
cls, |
parameterized_type.token_pos(), |
- bound_finalization, |
"type '%s' has an out of bound type argument", |
parameterized_type_name.ToCString())); |
return BoundedType::New(parameterized_type, |
@@ -942,10 +913,8 @@ |
// interface. |
ResolveType(cls, type, kCanonicalize); |
type = FinalizeType(cls, type, kCanonicalize); |
- // In production mode, a malformed result type is mapped to dynamic. |
- if (!FLAG_enable_type_checks && type.IsMalformed()) { |
- type = Type::DynamicType(); |
- } |
+ // A malformed result type is mapped to dynamic. |
+ ASSERT(!type.IsMalformed()); |
function.set_result_type(type); |
// Resolve formal parameter types. |
const intptr_t num_parameters = function.NumParameters(); |
@@ -953,10 +922,8 @@ |
type = function.ParameterTypeAt(i); |
ResolveType(cls, type, kCanonicalize); |
type = FinalizeType(cls, type, kCanonicalize); |
- // In production mode, a malformed parameter type is mapped to dynamic. |
- if (!FLAG_enable_type_checks && type.IsMalformed()) { |
- type = Type::DynamicType(); |
- } |
+ // A malformed parameter type is mapped to dynamic. |
+ ASSERT(!type.IsMalformed()); |
function.SetParameterTypeAt(i, type); |
} |
} |
@@ -1875,6 +1842,9 @@ |
// Resolve super type. Failures lead to a longjmp. |
ResolveType(cls, super_type, kCanonicalizeWellFormed); |
+ if (super_type.IsMalformed()) { |
+ ReportError(Error::Handle(super_type.malformed_error())); |
+ } |
if (super_type.IsDynamicType()) { |
const Script& script = Script::Handle(cls.script()); |
ReportError(script, cls.token_pos(), |
@@ -1940,6 +1910,9 @@ |
interface ^= super_interfaces.At(i); |
ResolveType(cls, interface, kCanonicalizeWellFormed); |
ASSERT(!interface.IsTypeParameter()); // Should be detected by parser. |
+ if (interface.IsMalformed()) { |
+ ReportError(Error::Handle(interface.malformed_error())); |
+ } |
if (interface.IsDynamicType()) { |
const Script& script = Script::Handle(cls.script()); |
ReportError(script, cls.token_pos(), |
@@ -2051,35 +2024,24 @@ |
void ClassFinalizer::ReportMalformedType(const Error& prev_error, |
const Class& cls, |
const Type& type, |
- FinalizationKind finalization, |
const char* format, |
va_list args) { |
LanguageError& error = LanguageError::Handle(); |
- if (FLAG_enable_type_checks || |
- !type.HasResolvedTypeClass() || |
- (finalization == kCanonicalizeWellFormed) || |
- FLAG_error_on_malformed_type) { |
- const Script& script = Script::Handle(cls.script()); |
- if (prev_error.IsNull()) { |
- error ^= Parser::FormatError( |
- script, type.token_pos(), "Error", format, args); |
- } else { |
- error ^= Parser::FormatErrorWithAppend( |
- prev_error, script, type.token_pos(), "Error", format, args); |
- } |
- if ((finalization == kCanonicalizeWellFormed) || |
- FLAG_error_on_malformed_type) { |
- ReportError(error); |
- } |
+ const Script& script = Script::Handle(cls.script()); |
+ if (prev_error.IsNull()) { |
+ error ^= Parser::FormatError( |
+ script, type.token_pos(), "Error", format, args); |
+ } else { |
+ error ^= Parser::FormatErrorWithAppend( |
+ prev_error, script, type.token_pos(), "Error", format, args); |
} |
- // In checked mode, always mark the type as malformed. |
- // In production mode, mark the type as malformed only if its type class is |
- // not resolved. |
- // In both mode, make the type raw, since it may not be possible to |
- // properly finalize its type arguments. |
- if (FLAG_enable_type_checks || !type.HasResolvedTypeClass()) { |
- type.set_malformed_error(error); |
+ if (FLAG_error_on_malformed_type) { |
+ ReportError(error); |
} |
+ type.set_malformed_error(error); |
+ // Make the type raw, since it may not be possible to |
+ // properly finalize its type arguments. |
+ type.set_type_class(Class::Handle(Object::dynamic_class())); |
type.set_arguments(Object::null_abstract_type_arguments()); |
if (!type.IsFinalized()) { |
type.SetIsFinalized(); |
@@ -2092,12 +2054,10 @@ |
} |
-RawType* ClassFinalizer::NewFinalizedMalformedType( |
- const Error& prev_error, |
- const Class& cls, |
- intptr_t type_pos, |
- FinalizationKind finalization, |
- const char* format, ...) { |
+RawType* ClassFinalizer::NewFinalizedMalformedType(const Error& prev_error, |
+ const Class& cls, |
+ intptr_t type_pos, |
+ const char* format, ...) { |
va_list args; |
va_start(args, format); |
const UnresolvedClass& unresolved_class = UnresolvedClass::Handle( |
@@ -2106,7 +2066,7 @@ |
type_pos)); |
const Type& type = Type::Handle( |
Type::New(unresolved_class, TypeArguments::Handle(), type_pos)); |
- ReportMalformedType(prev_error, cls, type, finalization, format, args); |
+ ReportMalformedType(prev_error, cls, type, format, args); |
va_end(args); |
ASSERT(type.IsMalformed()); |
ASSERT(type.IsFinalized()); |
@@ -2117,11 +2077,10 @@ |
void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, |
const Class& cls, |
const Type& type, |
- FinalizationKind finalization, |
const char* format, ...) { |
va_list args; |
va_start(args, format); |
- ReportMalformedType(prev_error, cls, type, finalization, format, args); |
+ ReportMalformedType(prev_error, cls, type, format, args); |
va_end(args); |
} |