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

Unified Diff: runtime/vm/parser.cc

Issue 10979053: Change many instance creation errors from compile-time errors to dynamic errors (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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.cc ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/parser.cc
===================================================================
--- runtime/vm/parser.cc (revision 12972)
+++ runtime/vm/parser.cc (working copy)
@@ -2453,12 +2453,19 @@
const intptr_t type_pos = TokenPos();
const AbstractType& type = AbstractType::Handle(
ParseType(ClassFinalizer::kTryResolve));
- if (type.IsTypeParameter()) {
- // TODO(regis): Spec is not clear. Throw dynamic error or report
- // compile-time error? Same question for new and const operators.
- ErrorMsg(type_pos, "factory may not redirect via a type parameter");
+ if (type.IsTypeParameter() || type.IsDynamicType()) {
+ // Replace the type with a malformed type and compile a throw when called.
+ redirection_type = ClassFinalizer::NewFinalizedMalformedType(
+ current_class(),
+ type_pos,
+ "factory '%s' may not redirect to %s'%s'",
+ method->name->ToCString(),
+ type.IsTypeParameter() ? "type parameter " : "",
+ type.IsTypeParameter() ?
+ String::Handle(type.UserVisibleName()).ToCString() : "dynamic");
+ } else {
+ redirection_type ^= type.raw();
}
- redirection_type ^= type.raw();
if (CurrentToken() == Token::kPERIOD) {
// Named constructor or factory.
ConsumeToken();
@@ -8858,29 +8865,19 @@
intptr_t type_pos = TokenPos();
AbstractType& type = AbstractType::Handle(
ParseType(ClassFinalizer::kCanonicalizeWellFormed));
- // Malformed bounds never result in a compile time error, therefore, the
- // parsed type may be malformed although we requested kCanonicalizeWellFormed.
- // In that case, we throw a dynamic type error instead of calling the
- // constructor.
- if (type.IsTypeParameter()) {
- ErrorMsg(type_pos,
- "type parameter '%s' cannot be instantiated",
- String::Handle(type.UserVisibleName()).ToCString());
+ // In case the type is malformed, throw a dynamic type error after finishing
+ // parsing the instance creation expression.
+ if (type.IsTypeParameter() || type.IsDynamicType()) {
+ // Replace the type with a malformed type.
+ type = ClassFinalizer::NewFinalizedMalformedType(
+ current_class(),
+ type_pos,
+ "%s'%s' cannot be instantiated",
+ type.IsTypeParameter() ? "type parameter " : "",
+ type.IsTypeParameter() ?
+ String::Handle(type.UserVisibleName()).ToCString() : "dynamic");
}
- if (type.IsDynamicType()) {
- ErrorMsg(type_pos, "Dynamic cannot be instantiated");
- }
- Class& type_class = Class::Handle(type.type_class());
- const String& type_class_name = String::Handle(type_class.Name());
- AbstractTypeArguments& type_arguments =
- AbstractTypeArguments::ZoneHandle(type.arguments());
- // The constructor class and its name are those of the parsed type, unless the
- // parsed type is an interface and a default factory class is specified, in
- // which case constructor_class and constructor_class_name are modified below.
- Class& constructor_class = Class::ZoneHandle(type_class.raw());
- String& constructor_class_name = String::Handle(type_class_name.raw());
-
// The grammar allows for an optional ('.' identifier)? after the type, which
// is a named constructor. Note that ParseType(kMustResolve) above will not
// consume it as part of a misinterpreted qualified identifier, because only a
@@ -8898,6 +8895,23 @@
intptr_t call_pos = TokenPos();
ArgumentListNode* arguments = ParseActualParameters(NULL, is_const);
+ // Parsing is complete, so we can return a throw in case of a malformed type.
+ if (type.IsMalformed()) {
+ return ThrowTypeError(type_pos, type);
+ }
+
+ // Resolve the type and optional identifier to a constructor or factory.
+ Class& type_class = Class::Handle(type.type_class());
+ const String& type_class_name = String::Handle(type_class.Name());
+ AbstractTypeArguments& type_arguments =
+ AbstractTypeArguments::ZoneHandle(type.arguments());
+
+ // The constructor class and its name are those of the parsed type, unless the
+ // parsed type is an interface and a default factory class is specified, in
+ // which case constructor_class and constructor_class_name are modified below.
+ Class& constructor_class = Class::ZoneHandle(type_class.raw());
+ String& constructor_class_name = String::Handle(type_class_name.raw());
+
// A constructor has an implicit 'this' parameter (instance to construct)
// and a factory has an implicit 'this' parameter (type_arguments).
// A constructor has a second implicit 'phase' parameter.
@@ -8913,22 +8927,32 @@
Function& constructor = Function::ZoneHandle(
type_class.LookupConstructor(constructor_name));
if (constructor.IsNull()) {
- ErrorMsg(type_pos,
- "interface '%s' has no constructor named '%s'",
- type_class_name.ToCString(),
- external_constructor_name.ToCString());
+ // Replace the type with a malformed type and compile a throw.
+ type = ClassFinalizer::NewFinalizedMalformedType(
+ current_class(),
+ type_pos,
+ "interface '%s' has no constructor named '%s'",
+ type_class_name.ToCString(),
+ external_constructor_name.ToCString());
+ return ThrowTypeError(type_pos, type);
}
+ // TODO(regis): Throw a NoSuchMethodError instead of a TypeError.
String& error_message = String::Handle();
if (!constructor.AreValidArguments(arguments_length,
arguments->names(),
&error_message)) {
- ErrorMsg(call_pos,
- "invalid arguments passed to constructor '%s' "
- "for interface '%s': %s",
- external_constructor_name.ToCString(),
- type_class_name.ToCString(),
- error_message.ToCString());
+ // Replace the type with a malformed type and compile a throw.
+ type = ClassFinalizer::NewFinalizedMalformedType(
+ current_class(),
+ call_pos,
+ "invalid arguments passed to constructor '%s' "
+ "for interface '%s': %s",
+ external_constructor_name.ToCString(),
+ type_class_name.ToCString(),
+ error_message.ToCString());
+ return ThrowTypeError(call_pos, type);
}
+ // TODO(regis): Remove support for obsolete default factory classes.
if (!type_class.HasFactoryClass()) {
ErrorMsg(type_pos,
"cannot allocate interface '%s' without factory class",
@@ -8968,26 +8992,27 @@
if (constructor.IsNull()) {
const String& external_constructor_name =
(named_constructor ? constructor_name : constructor_class_name);
- ErrorMsg(type_pos,
- "class '%s' has no constructor or factory named '%s'",
- String::Handle(constructor_class.Name()).ToCString(),
- external_constructor_name.ToCString());
+ // Replace the type with a malformed type and compile a throw.
+ type = ClassFinalizer::NewFinalizedMalformedType(
+ current_class(),
+ type_pos,
+ "class '%s' has no constructor or factory named '%s'",
+ String::Handle(constructor_class.Name()).ToCString(),
+ external_constructor_name.ToCString());
+ return ThrowTypeError(type_pos, type);
} else if (constructor.IsRedirectingFactory()) {
type = constructor.RedirectionType();
+ if (type.IsMalformed()) {
+ return ThrowTypeError(type.token_pos(), type);
+ }
constructor = constructor.RedirectionTarget();
- if (constructor.IsNull()) {
- // TODO(regis): We normally report a compile-time error if the
- // constructor is not found. See above. However, we should throw a
- // dynamic error instead. We do it here. This is the first step.
- ASSERT(type.IsMalformed());
- } else {
- type_class = type.type_class();
- type_arguments = type.arguments();
- constructor_class = constructor.Owner();
- ASSERT(type_class.raw() == constructor_class.raw());
- }
+ ASSERT(!constructor.IsNull());
+ type_class = type.type_class();
+ type_arguments = type.arguments();
+ constructor_class = constructor.Owner();
+ ASSERT(type_class.raw() == constructor_class.raw());
}
- if (!constructor.IsNull() && constructor.IsFactory()) {
+ if (constructor.IsFactory()) {
// A factory does not have the implicit 'phase' parameter.
arguments_length -= 1;
}
@@ -8995,8 +9020,8 @@
// It is ok to call a factory method of an abstract class, but it is
// a dynamic error to instantiate an abstract class.
- if (!constructor.IsNull() &&
- constructor_class.is_abstract() &&
+ ASSERT(!constructor.IsNull());
+ if (constructor_class.is_abstract() &&
!constructor.IsFactory()) {
ArgumentListNode* arguments = new ArgumentListNode(type_pos);
arguments->Add(new LiteralNode(
@@ -9008,19 +9033,22 @@
const String& func_name = String::Handle(Symbols::ThrowNew());
return MakeStaticCall(cls_name, func_name, arguments);
}
-
+ // TODO(regis): Throw a NoSuchMethodError instead of a TypeError.
String& error_message = String::Handle();
- if (!constructor.IsNull() &&
- !constructor.AreValidArguments(arguments_length,
+ if (!constructor.AreValidArguments(arguments_length,
arguments->names(),
&error_message)) {
const String& external_constructor_name =
(named_constructor ? constructor_name : constructor_class_name);
- ErrorMsg(call_pos,
- "invalid arguments passed to constructor '%s' for class '%s': %s",
- external_constructor_name.ToCString(),
- String::Handle(constructor_class.Name()).ToCString(),
- error_message.ToCString());
+ // Replace the type with a malformed type and compile a throw when called.
+ type = ClassFinalizer::NewFinalizedMalformedType(
+ current_class(),
+ call_pos,
+ "invalid arguments passed to constructor '%s' for class '%s': %s",
+ external_constructor_name.ToCString(),
+ String::Handle(constructor_class.Name()).ToCString(),
+ error_message.ToCString());
+ return ThrowTypeError(call_pos, type);
}
// Now that the constructor to be called is identified, finalize the type
@@ -9066,8 +9094,7 @@
}
}
if (type.IsMalformed()) {
- // Compile the throw of a dynamic type error due to a bound error or to
- // a redirection error.
+ // Return the throw of a dynamic type error if the type is malformed.
return ThrowTypeError(type_pos, type);
}
type_arguments ^= type_arguments.Canonicalize();
« no previous file with comments | « runtime/vm/class_finalizer.cc ('k') | tests/co19/co19-runtime.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698