Chromium Code Reviews| Index: runtime/vm/class_finalizer.cc |
| =================================================================== |
| --- runtime/vm/class_finalizer.cc (revision 5060) |
| +++ runtime/vm/class_finalizer.cc (working copy) |
| @@ -166,15 +166,22 @@ |
| class_name.ToCString(), |
| interface_name.ToCString(), |
| function_name.ToCString()); |
| - } else if (!class_function.IsSubtypeOf(TypeArguments::Handle(), |
| + } else { |
| + Error& malformed_error = Error::Handle(); |
| + if (!class_function.IsSubtypeOf(TypeArguments::Handle(), |
| interface_function, |
| - TypeArguments::Handle())) { |
| - OS::Print("The type of instance method '%s' in class '%s' is not a " |
| - "subtype of the type of '%s' in interface '%s'\n", |
| - function_name.ToCString(), |
| - class_name.ToCString(), |
| - function_name.ToCString(), |
| - interface_name.ToCString()); |
| + TypeArguments::Handle(), |
| + &malformed_error)) { |
| + if (!malformed_error.IsNull()) { |
| + OS::Print("%s\n", malformed_error.ToErrorCString()); |
|
srdjan
2012/03/07 00:41:23
Shouldn't this be going to PrintErr?
regis
2012/03/07 02:22:38
Done.
|
| + } |
| + OS::Print("The type of instance method '%s' in class '%s' is not a " |
| + "subtype of the type of '%s' in interface '%s'\n", |
| + function_name.ToCString(), |
| + class_name.ToCString(), |
| + function_name.ToCString(), |
| + interface_name.ToCString()); |
| + } |
| } |
| } |
| } |
| @@ -453,7 +460,8 @@ |
| parameterized_type.set_type_class(Object::Handle(type_class.raw())); |
| } else { |
| // The type class could not be resolved. The type is malformed. |
| - FinalizeMalformedType(cls, parameterized_type, finalization, |
| + FinalizeMalformedType(Error::Handle(), // No previous error. |
| + cls, parameterized_type, finalization, |
| "cannot resolve class name '%s' from '%s'", |
| String::Handle(unresolved_class.Name()).ToCString(), |
| String::Handle(cls.Name()).ToCString()); |
| @@ -553,6 +561,7 @@ |
| 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.Name()).ToCString()); |
| @@ -612,6 +621,7 @@ |
| if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) { |
| // Wrong number of type arguments. The type is malformed. |
| FinalizeMalformedType( |
| + Error::Handle(), // No previous error. |
| cls, parameterized_type, finalization, |
| "wrong number of type arguments in type '%s'", |
| String::Handle(parameterized_type.Name()).ToCString()); |
| @@ -652,8 +662,27 @@ |
| // Mark the type as finalized. |
| parameterized_type.set_is_finalized(); |
| - // No need to verify the upper bounds of the finalized type arguments, since |
| - // bound errors are static type errors, which are not reported by the VM. |
| + // Upper bounds of the finalized type arguments are only verified in checked |
| + // mode, since bound errors are never reported by the vm in production mode. |
| + if (FLAG_enable_type_checks && full_arguments.IsInstantiated()) { |
| + ResolveAndFinalizeUpperBounds(type_class); |
| + Error& malformed_error = Error::Handle(); |
| + // Pass the full type argument vector as the bounds instantiator. |
| + if (!full_arguments.IsWithinBoundsOf(type_class, |
| + full_arguments, |
| + &malformed_error)) { |
| + ASSERT(!malformed_error.IsNull()); |
| + // The type argument vector of the type is not within bounds. The type |
| + // is malformed. Prepend malformed_error to new malformed type error in |
| + // order to report both locations. |
| + FinalizeMalformedType( |
| + malformed_error, |
| + cls, parameterized_type, finalization, |
| + "type arguments of type '%s' are not within bounds", |
| + String::Handle(parameterized_type.Name()).ToCString()); |
| + return parameterized_type.raw(); |
| + } |
| + } |
| } else { |
| parameterized_type.set_is_finalized(); |
| } |
| @@ -1173,7 +1202,8 @@ |
| } |
| -void ClassFinalizer::FinalizeMalformedType(const Class& cls, |
| +void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, |
| + const Class& cls, |
| const Type& type, |
| FinalizationKind finalization, |
| const char* format, ...) { |
| @@ -1182,8 +1212,13 @@ |
| LanguageError& error = LanguageError::Handle(); |
| if ((finalization == kFinalizeWellFormed) || FLAG_enable_type_checks) { |
| const Script& script = Script::Handle(cls.script()); |
| - error ^= |
| - Parser::FormatError(script, type.token_index(), "Error", format, args); |
| + if (prev_error.IsNull()) { |
| + error ^= Parser::FormatError( |
| + script, type.token_index(), "Error", format, args); |
| + } else { |
| + error ^= Parser::FormatErrorWithAppend( |
| + prev_error, script, type.token_index(), "Error", format, args); |
| + } |
| if (finalization == kFinalizeWellFormed) { |
| ReportError(error); |
| } |
| @@ -1195,8 +1230,14 @@ |
| // In checked mode, mark type as malformed. |
| type.set_malformed_error(error); |
| } |
| - type.set_is_finalized(); |
| - type.Canonicalize(); |
| + if (!type.IsFinalized()) { |
| + type.set_is_finalized(); |
| + type.Canonicalize(); |
| + } else { |
| + // The only case where the malformed type was already finalized is when its |
| + // type arguments are not within bounds. In that case, we have a prev_error. |
| + ASSERT(!prev_error.IsNull()); |
| + } |
| } |