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

Unified Diff: runtime/vm/parser.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
Index: runtime/vm/parser.cc
===================================================================
--- runtime/vm/parser.cc (revision 24923)
+++ runtime/vm/parser.cc (working copy)
@@ -1281,7 +1281,7 @@
// mode, because they are part of the function type of closurized
// functions appearing in type tests with typedefs.
parameter.type = &AbstractType::ZoneHandle(
- ParseType(is_top_level_ ? ClassFinalizer::kTryResolve :
+ ParseType(is_top_level_ ? ClassFinalizer::kResolveTypeParameters :
ClassFinalizer::kCanonicalize));
} else {
parameter.type = &Type::ZoneHandle(Type::DynamicType());
@@ -2800,20 +2800,17 @@
ConsumeToken();
const intptr_t type_pos = TokenPos();
const AbstractType& type = AbstractType::Handle(
- ParseType(ClassFinalizer::kTryResolve));
- if (!type.IsMalformed() &&
- (type.IsTypeParameter() || type.IsDynamicType())) {
+ ParseType(ClassFinalizer::kResolveTypeParameters));
+ if (!type.IsMalformed() && type.IsTypeParameter()) {
// Replace the type with a malformed type and compile a throw when called.
redirection_type = ClassFinalizer::NewFinalizedMalformedType(
Error::Handle(), // No previous error.
current_class(),
type_pos,
- ClassFinalizer::kTryResolve, // No compile-time error.
- "factory '%s' may not redirect to %s'%s'",
+ ClassFinalizer::kResolveTypeParameters, // No compile-time error.
+ "factory '%s' may not redirect to type parameter '%s'",
method->name->ToCString(),
- type.IsTypeParameter() ? "type parameter " : "",
- type.IsTypeParameter() ?
- String::Handle(type.UserVisibleName()).ToCString() : "dynamic");
+ String::Handle(type.UserVisibleName()).ToCString());
} else {
redirection_type ^= type.raw();
}
@@ -3215,7 +3212,7 @@
// because getters and setters could be closurized at some time (not
// supported yet).
member.type = &AbstractType::ZoneHandle(
- ParseType(ClassFinalizer::kTryResolve));
+ ParseType(ClassFinalizer::kResolveTypeParameters));
}
}
}
@@ -3464,18 +3461,13 @@
if (CurrentToken() == Token::kEXTENDS) {
ConsumeToken();
const intptr_t type_pos = TokenPos();
- super_type = ParseType(ClassFinalizer::kTryResolve);
+ super_type = ParseType(ClassFinalizer::kResolveTypeParameters);
if (super_type.IsTypeParameter()) {
ErrorMsg(type_pos,
"class '%s' may not extend type parameter '%s'",
class_name.ToCString(),
String::Handle(super_type.UserVisibleName()).ToCString());
}
- if (super_type.IsDynamicType()) {
- ErrorMsg(type_pos,
- "class '%s' may not extend 'dynamic'",
- class_name.ToCString());
- }
if (CurrentToken() == Token::kWITH) {
super_type = ParseMixins(super_type);
}
@@ -3671,7 +3663,7 @@
const intptr_t type_pos = TokenPos();
AbstractType& type =
- AbstractType::Handle(ParseType(ClassFinalizer::kTryResolve));
+ AbstractType::Handle(ParseType(ClassFinalizer::kResolveTypeParameters));
if (type.IsTypeParameter()) {
ErrorMsg(type_pos,
"class '%s' may not extend type parameter '%s'",
@@ -3787,7 +3779,7 @@
// result type.
if (!result_type.IsNull()) {
ResolveTypeFromClass(function_type_alias,
- ClassFinalizer::kTryResolve,
+ ClassFinalizer::kResolveTypeParameters,
&result_type);
}
// Parse the formal parameters of the function type.
@@ -3984,7 +3976,7 @@
type_parameter ^= type_parameters.TypeAt(i);
type_parameter_bound = type_parameter.bound();
ResolveTypeFromClass(cls,
- ClassFinalizer::kTryResolve,
+ ClassFinalizer::kResolveTypeParameters,
&type_parameter_bound);
type_parameter.set_bound(type_parameter_bound);
}
@@ -4046,15 +4038,12 @@
do {
ConsumeToken();
intptr_t interface_pos = TokenPos();
- interface = ParseType(ClassFinalizer::kTryResolve);
+ interface = ParseType(ClassFinalizer::kResolveTypeParameters);
if (interface.IsTypeParameter()) {
ErrorMsg(interface_pos,
"type parameter '%s' may not be used in interface list",
String::Handle(interface.UserVisibleName()).ToCString());
}
- if (interface.IsDynamicType()) {
- ErrorMsg(interface_pos, "'dynamic' may not be used in interface list");
- }
all_interfaces.Add(interface);
} while (CurrentToken() == Token::kCOMMA);
cls_interfaces = Array::MakeArray(all_interfaces);
@@ -4080,7 +4069,7 @@
do {
ConsumeToken();
const intptr_t mixin_pos = TokenPos();
- mixin_type = ParseType(ClassFinalizer::kTryResolve);
+ mixin_type = ParseType(ClassFinalizer::kResolveTypeParameters);
if (mixin_type.IsTypeParameter()) {
ErrorMsg(mixin_pos,
"mixin type '%s' may not be a type parameter",
@@ -4113,7 +4102,7 @@
// to get the copy is to rewind the parser, parse the mixin type
// again and steal its type arguments.
SetPosition(mixin_pos);
- mixin_type = ParseType(ClassFinalizer::kTryResolve);
+ mixin_type = ParseType(ClassFinalizer::kResolveTypeParameters);
mixin_type_arguments = mixin_type.arguments();
mixin_application_type = Type::New(mixin_application,
@@ -4136,7 +4125,7 @@
const bool is_static = true;
const AbstractType& type =
AbstractType::ZoneHandle(ParseConstFinalVarOrType(
- FLAG_enable_type_checks ? ClassFinalizer::kTryResolve :
+ FLAG_enable_type_checks ? ClassFinalizer::kResolveTypeParameters :
ClassFinalizer::kIgnore));
Field& field = Field::Handle();
Function& getter = Function::Handle();
@@ -4234,7 +4223,7 @@
// Parse optional type.
if ((CurrentToken() == Token::kIDENT) &&
(LookaheadToken(1) != Token::kLPAREN)) {
- result_type = ParseType(ClassFinalizer::kTryResolve);
+ result_type = ParseType(ClassFinalizer::kResolveTypeParameters);
}
}
const intptr_t name_pos = TokenPos();
@@ -4328,7 +4317,7 @@
ConsumeToken();
result_type = Type::VoidType();
} else {
- result_type = ParseType(ClassFinalizer::kTryResolve);
+ result_type = ParseType(ClassFinalizer::kResolveTypeParameters);
}
is_getter = (CurrentToken() == Token::kGET);
if (CurrentToken() == Token::kGET || CurrentToken() == Token::kSET) {
@@ -5324,25 +5313,27 @@
bool Parser::IsSimpleLiteral(const AbstractType& type, Instance* value) {
- bool no_check = type.IsDynamicType();
- if ((CurrentToken() == Token::kINTEGER) &&
- (no_check || type.IsIntType() || type.IsNumberType())) {
+ // If the type of the const field is guaranteed to be instantiated once
+ // resolved at class finalization time, and if the type of the literal is one
+ // of int, double, String, or bool, then preset the field with the value and
+ // perform the type check (in checked mode only) at finalization time.
+ if (type.IsTypeParameter() || // Always resolved at parse time.
+ (type.arguments() != AbstractTypeArguments::null())) {
+ return false;
+ }
+ if (CurrentToken() == Token::kINTEGER) {
*value = CurrentIntegerLiteral();
return true;
- } else if ((CurrentToken() == Token::kDOUBLE) &&
- (no_check || type.IsDoubleType() || type.IsNumberType())) {
+ } else if (CurrentToken() == Token::kDOUBLE) {
*value = CurrentDoubleLiteral();
return true;
- } else if ((CurrentToken() == Token::kSTRING) &&
- (no_check || type.IsStringType())) {
+ } else if (CurrentToken() == Token::kSTRING) {
*value = CurrentLiteral()->raw();
return true;
- } else if ((CurrentToken() == Token::kTRUE) &&
- (no_check || type.IsBoolType())) {
+ } else if (CurrentToken() == Token::kTRUE) {
*value = Bool::True().raw();
return true;
- } else if ((CurrentToken() == Token::kFALSE) &&
- (no_check || type.IsBoolType())) {
+ } else if (CurrentToken() == Token::kFALSE) {
*value = Bool::False().raw();
return true;
} else if (CurrentToken() == Token::kNULL) {
@@ -8002,7 +7993,7 @@
void Parser::ResolveTypeFromClass(const Class& scope_class,
ClassFinalizer::FinalizationKind finalization,
AbstractType* type) {
- ASSERT(finalization >= ClassFinalizer::kTryResolve);
+ ASSERT(finalization >= ClassFinalizer::kResolveTypeParameters);
ASSERT(type != NULL);
if (type->IsResolved()) {
return;
@@ -8050,25 +8041,29 @@
return;
}
}
- // Resolve classname in the scope of the current library.
- Error& error = Error::Handle();
- // If we finalize a type expression, as opposed to a type annotation, we
- // tell the resolver (by passing NULL) to immediately report an ambiguous
- // type as a compile time error.
- resolved_type_class = ResolveClassInCurrentLibraryScope(
- unresolved_class.token_pos(),
- unresolved_class_name,
- finalization >= ClassFinalizer::kCanonicalizeExpression ?
- NULL : &error);
- if (!error.IsNull()) {
- *type = ClassFinalizer::NewFinalizedMalformedType(
- error,
- scope_class,
+ // The referenced class may not have been parsed yet. It would be wrong
+ // to resolve it too early to an imported class of the same name.
+ if (finalization > ClassFinalizer::kResolveTypeParameters) {
+ // Resolve classname in the scope of the current library.
+ Error& error = Error::Handle();
+ // If we finalize a type expression, as opposed to a type annotation,
+ // we tell the resolver (by passing NULL) to immediately report an
+ // ambiguous type as a compile time error.
+ resolved_type_class = ResolveClassInCurrentLibraryScope(
unresolved_class.token_pos(),
- finalization,
- "cannot resolve class '%s'",
- unresolved_class_name.ToCString());
- return;
+ unresolved_class_name,
+ finalization >= ClassFinalizer::kCanonicalizeExpression ?
+ NULL : &error);
+ if (!error.IsNull()) {
+ *type = ClassFinalizer::NewFinalizedMalformedType(
+ error,
+ scope_class,
+ unresolved_class.token_pos(),
+ finalization,
+ "cannot resolve class '%s'",
+ unresolved_class_name.ToCString());
+ return;
+ }
}
} else {
LibraryPrefix& lib_prefix =
@@ -8530,8 +8525,8 @@
if (first_lib_url.raw() == lib.url()) {
ambiguous_ref_error = FormatErrorMsg(
script_, ident_pos, "Error",
- "ambiguous reference: "
- "'%s' as library '%s' is imported multiple times",
+ "ambiguous reference to '%s', "
+ "as library '%s' is imported multiple times",
name.ToCString(),
first_lib_url.ToCString());
} else {
@@ -8850,7 +8845,7 @@
parameterized_type.set_arguments(Object::null_abstract_type_arguments());
parameterized_type.set_malformed_error(malformed_error);
}
- if (finalization >= ClassFinalizer::kTryResolve) {
+ if (finalization >= ClassFinalizer::kResolveTypeParameters) {
ResolveTypeFromClass(current_class(), finalization, &type);
if (finalization >= ClassFinalizer::kCanonicalize) {
type ^= ClassFinalizer::FinalizeType(current_class(), type, finalization);
@@ -9305,7 +9300,7 @@
Error::Handle(), // No previous error.
current_class(),
type_pos,
- ClassFinalizer::kTryResolve, // No compile-time error.
+ ClassFinalizer::kResolveTypeParameters, // No compile-time error.
"%s'%s' cannot be instantiated",
type.IsTypeParameter() ? "type parameter " : "",
type.IsTypeParameter() ?
@@ -9371,7 +9366,7 @@
Error::Handle(), // No previous error.
current_class(),
call_pos,
- ClassFinalizer::kTryResolve, // No compile-time error.
+ ClassFinalizer::kResolveTypeParameters, // No compile-time error.
"class '%s' has no constructor or factory named '%s'",
String::Handle(type_class.Name()).ToCString(),
external_constructor_name.ToCString());
@@ -9489,7 +9484,7 @@
malformed_error,
current_class(),
new_pos,
- ClassFinalizer::kTryResolve, // No compile-time error.
+ ClassFinalizer::kResolveTypeParameters, // No compile-time error.
"const factory result is not an instance of '%s'",
String::Handle(type_bound.UserVisibleName()).ToCString());
new_object = ThrowTypeError(new_pos, type_bound);
« runtime/vm/object.cc ('K') | « runtime/vm/object.cc ('k') | tests/language/language.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698