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

Unified Diff: runtime/vm/class_finalizer.cc

Issue 19030004: Stop resolving classes prematurely in the vm (issue 11023). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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/class_finalizer.h ('k') | runtime/vm/mirrors_api_impl.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/class_finalizer.cc
===================================================================
--- runtime/vm/class_finalizer.cc (revision 24964)
+++ runtime/vm/class_finalizer.cc (working copy)
@@ -255,15 +255,59 @@
// Resolve unresolved_class in the library of cls, or return null.
-RawClass* ClassFinalizer::ResolveClass(
- const Class& cls, const UnresolvedClass& unresolved_class) {
+RawClass* ClassFinalizer::ResolveClass(const Class& cls,
+ const UnresolvedClass& unresolved_class,
+ Error* ambiguity_error) {
const String& class_name = String::Handle(unresolved_class.ident());
Library& lib = Library::Handle();
Class& resolved_class = Class::Handle();
if (unresolved_class.library_prefix() == LibraryPrefix::null()) {
lib = cls.library();
ASSERT(!lib.IsNull());
- resolved_class = lib.LookupClass(class_name);
+ // TODO(regis): Call lib.LookupClass(class_name, ambiguity_error) instead
+ // once it takes the ambiguity_error parameter.
+
+ // First check if name is found in the local scope of the library.
+ Object& obj = Object::Handle(lib.LookupLocalObject(class_name));
+ if (!obj.IsNull() && obj.IsClass()) {
+ return Class::Cast(obj).raw();
+ }
+ // Now check if class_name is found in any imported libs.
+ String& first_lib_url = String::Handle();
+ Namespace& import = Namespace::Handle();
+ Library& import_lib = Library::Handle();
+ for (intptr_t i = 0; i < lib.num_imports(); i++) {
+ import ^= lib.ImportAt(i);
+ obj = import.Lookup(class_name);
+ if (!obj.IsNull()) {
+ import_lib = import.library();
+ if (!first_lib_url.IsNull()) {
+ // Found duplicate definition.
+ const Script& script = Script::Handle(cls.script());
+ if (first_lib_url.raw() == lib.url()) {
+ *ambiguity_error = Parser::FormatErrorMsg(
+ script, unresolved_class.token_pos(), "Error",
+ "ambiguous reference to '%s', "
+ "as library '%s' is imported multiple times",
+ class_name.ToCString(),
+ first_lib_url.ToCString());
+ } else {
+ *ambiguity_error = Parser::FormatErrorMsg(
+ script, unresolved_class.token_pos(), "Error",
+ "ambiguous reference: "
+ "'%s' is defined in library '%s' and also in '%s'",
+ class_name.ToCString(),
+ first_lib_url.ToCString(),
+ String::Handle(lib.url()).ToCString());
+ }
+ return Class::null();
+ }
+ first_lib_url = lib.url();
+ if (obj.IsClass()) {
+ resolved_class = Class::Cast(obj).raw();
+ }
+ }
+ }
} else {
LibraryPrefix& lib_prefix = LibraryPrefix::Handle();
lib_prefix = unresolved_class.library_prefix();
@@ -317,6 +361,19 @@
ASSERT(factory.RedirectionTarget() == Function::null());
return;
}
+ ASSERT(!type.IsTypeParameter()); // Resolved in parser.
+ if (type.IsDynamicType()) {
+ // Replace the type with a malformed type and compile a throw when called.
+ type = NewFinalizedMalformedType(
+ 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());
+ return;
+ }
const Class& target_class = Class::Handle(type.type_class());
String& target_class_name = String::Handle(target_class.Name());
String& target_name = String::Handle(
@@ -339,7 +396,7 @@
Error::Handle(), // No previous error.
cls,
factory.token_pos(),
- kTryResolve, // No compile-time error.
+ kResolveTypeParameters, // No compile-time error.
"class '%s' has no constructor or factory named '%s'",
target_class_name.ToCString(),
user_visible_target_name.ToCString());
@@ -354,7 +411,7 @@
Error::Handle(), // No previous error.
cls,
factory.token_pos(),
- kTryResolve, // No compile-time error.
+ kResolveTypeParameters, // No compile-time error.
"constructor '%s' has incompatible parameters with "
"redirecting factory '%s'",
String::Handle(target.name()).ToCString(),
@@ -437,8 +494,9 @@
// Lookup the type class.
const UnresolvedClass& unresolved_class =
UnresolvedClass::Handle(type.unresolved_class());
+ Error& ambiguous_error = Error::Handle();
const Class& type_class =
- Class::Handle(ResolveClass(cls, unresolved_class));
+ Class::Handle(ResolveClass(cls, unresolved_class, &ambiguous_error));
// Replace unresolved class with resolved type class.
const Type& parameterized_type = Type::Cast(type);
@@ -446,7 +504,7 @@
parameterized_type.set_type_class(type_class);
} else {
// The type class could not be resolved. The type is malformed.
- FinalizeMalformedType(Error::Handle(), // No previous error.
+ FinalizeMalformedType(ambiguous_error, // May be null.
cls, parameterized_type, finalization,
"cannot resolve class name '%s' from '%s'",
String::Handle(unresolved_class.Name()).ToCString(),
@@ -870,7 +928,8 @@
// If a bound error occurred, return a BoundedType with a malformed bound.
// The malformed bound will be ignored in production mode.
if (!bound_error.IsNull()) {
- FinalizationKind bound_finalization = kTryResolve; // No compile error.
+ // No compile-time error during finalization.
+ FinalizationKind bound_finalization = kResolveTypeParameters;
if (FLAG_enable_type_checks || FLAG_error_on_malformed_type) {
bound_finalization = finalization;
}
@@ -1062,6 +1121,43 @@
super_class_name.ToCString());
}
}
+ if ((FLAG_enable_type_checks || FLAG_error_on_malformed_type) &&
+ field.is_static() && field.is_const() &&
+ (field.value() != Object::null()) &&
+ (field.value() != Object::sentinel().raw())) {
+ // The parser does not preset the value if the type is a type parameter or
+ // is parameterized unless the value is null.
+ Error& malformed_error = Error::Handle();
+ if (type.IsMalformed()) {
+ malformed_error = type.malformed_error();
+ } else {
+ ASSERT(type.IsInstantiated());
+ }
+ const Instance& const_value = Instance::Handle(field.value());
+ if (!malformed_error.IsNull() ||
+ (!type.IsDynamicType() &&
+ !const_value.IsInstanceOf(type,
+ AbstractTypeArguments::Handle(),
+ &malformed_error))) {
+ // If the failure is due to a malformed type error, display it instead.
+ if (!malformed_error.IsNull()) {
+ ReportError(malformed_error);
+ } else {
+ const AbstractType& const_value_type = AbstractType::Handle(
+ const_value.GetType());
+ const String& const_value_type_name = String::Handle(
+ const_value_type.UserVisibleName());
+ const String& type_name = String::Handle(type.UserVisibleName());
+ const Script& script = Script::Handle(cls.script());
+ ReportError(script, field.token_pos(),
+ "error initializing const field '%s': type '%s' is not a "
+ "subtype of type '%s'",
+ name.ToCString(),
+ const_value_type_name.ToCString(),
+ type_name.ToCString());
+ }
+ }
+ }
}
// Collect interfaces, super interfaces, and super classes of this class.
const GrowableObjectArray& interfaces =
@@ -1709,6 +1805,12 @@
// Resolve super type. Failures lead to a longjmp.
ResolveType(cls, super_type, kCanonicalizeWellFormed);
+ if (super_type.IsDynamicType()) {
+ const Script& script = Script::Handle(cls.script());
+ ReportError(script, cls.token_pos(),
+ "class '%s' may not extend 'dynamic'",
+ String::Handle(cls.Name()).ToCString());
+ }
interface_class = super_type.type_class();
// If cls belongs to core lib or to core lib's implementation, restrictions
@@ -1767,11 +1869,11 @@
for (intptr_t i = 0; i < super_interfaces.Length(); i++) {
interface ^= super_interfaces.At(i);
ResolveType(cls, interface, kCanonicalizeWellFormed);
- if (interface.IsTypeParameter()) {
+ ASSERT(!interface.IsTypeParameter()); // Should be detected by parser.
+ if (interface.IsDynamicType()) {
const Script& script = Script::Handle(cls.script());
ReportError(script, cls.token_pos(),
- "type parameter '%s' cannot be used as interface",
- String::Handle(interface.Name()).ToCString());
+ "'dynamic' may not be used as interface");
}
interface_class = interface.type_class();
if (interface_class.IsSignatureClass()) {
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/mirrors_api_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698