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

Unified Diff: runtime/vm/parser.cc

Issue 9615035: Generate dynamic type errors according to spec. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 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 5060)
+++ runtime/vm/parser.cc (working copy)
@@ -5373,6 +5373,12 @@
}
+void Parser::ErrorMsg(const Error& error) {
+ Isolate::Current()->long_jump_base()->Jump(1, error);
+ UNREACHABLE();
+}
+
+
void Parser::AppendErrorMsg(
const Error& prev_error, intptr_t token_index, const char* format, ...) {
va_list args;
@@ -5553,6 +5559,7 @@
}
right_operand = new TypeNode(type_pos, type);
if (type.IsMalformed()) {
+ // Note that a type error is thrown even if the tested value is null.
return ThrowTypeError(type_pos, type);
}
}
@@ -6393,6 +6400,7 @@
} else if (finalization >= ClassFinalizer::kFinalize) {
// The type is malformed.
ClassFinalizer::FinalizeMalformedType(
+ Error::Handle(), // No previous error.
current_class(), parameterized_type, finalization,
"type '%s' is not loaded",
String::Handle(parameterized_type.Name()).ToCString());
@@ -6967,10 +6975,13 @@
// The expression needs to be type checked at runtime.
// Eliminate the type check if it can be performed at compile time and
// if it succeeds.
+ Error& malformed_error = Error::Handle();
if (!element_type.IsInstantiated() ||
!element->IsLiteralNode() ||
!element->AsLiteralNode()->literal().
- IsAssignableTo(element_type, TypeArguments::Handle())) {
+ IsAssignableTo(element_type,
+ TypeArguments::Handle(),
+ &malformed_error)) {
element = new AssignableNode(element_pos,
element,
element_type,
@@ -6993,20 +7004,25 @@
Array& const_list =
Array::ZoneHandle(Array::New(list->length(), Heap::kOld));
const_list.SetTypeArguments(type_arguments);
-
+ Error& malformed_error = Error::Handle();
for (int i = 0; i < list->length(); i++) {
AstNode* elem = list->ElementAt(i);
// Arguments have been evaluated to a literal value already.
ASSERT(elem->IsLiteralNode());
if (FLAG_enable_type_checks &&
!element_type.IsDynamicType() &&
- !elem->AsLiteralNode()->literal().
- IsAssignableTo(element_type, TypeArguments::Handle())) {
- ErrorMsg(elem->AsLiteralNode()->token_index(),
- "list literal element at index %d must be "
- "a constant of type '%s'",
- i,
- String::Handle(element_type.Name()).ToCString());
+ !elem->AsLiteralNode()->literal().IsAssignableTo(
+ element_type, TypeArguments::Handle(), &malformed_error)) {
+ // If the failure is due to a malformed type error, display it instead.
+ if (!malformed_error.IsNull()) {
+ ErrorMsg(malformed_error);
+ } else {
+ ErrorMsg(elem->AsLiteralNode()->token_index(),
+ "list literal element at index %d must be "
+ "a constant of type '%s'",
+ i,
+ String::Handle(element_type.Name()).ToCString());
+ }
}
const_list.SetAt(i, elem->AsLiteralNode()->literal());
}
@@ -7144,10 +7160,11 @@
// The expression needs to be type checked at runtime.
// Eliminate the type check if it can be performed at compile time and
// if it succeeds.
+ Error& malformed_error = Error::Handle();
if (!value_type.IsInstantiated() ||
!value->IsLiteralNode() ||
- !value->AsLiteralNode()->literal().
- IsAssignableTo(value_type, TypeArguments::Handle())) {
+ !value->AsLiteralNode()->literal().IsAssignableTo(
+ value_type, TypeArguments::Handle(), &malformed_error)) {
value = new AssignableNode(value_pos,
value,
value_type,
@@ -7173,6 +7190,7 @@
// First, create the canonicalized key-value pair array.
Array& key_value_array =
Array::ZoneHandle(Array::New(kv_pairs->length(), Heap::kOld));
+ Error& malformed_error = Error::Handle();
for (int i = 0; i < kv_pairs->length(); i++) {
AstNode* arg = kv_pairs->ElementAt(i);
// Arguments have been evaluated to a literal value already.
@@ -7180,13 +7198,18 @@
if (FLAG_enable_type_checks &&
((i % 2) == 1) && // Check values only, not keys.
!value_type.IsDynamicType() &&
- !arg->AsLiteralNode()->literal().
- IsAssignableTo(value_type, TypeArguments::Handle())) {
- ErrorMsg(arg->AsLiteralNode()->token_index(),
- "map literal value at index %d must be "
- "a constant of type '%s'",
- i >> 1,
- String::Handle(value_type.Name()).ToCString());
+ !arg->AsLiteralNode()->literal().IsAssignableTo(
+ value_type, TypeArguments::Handle(), &malformed_error)) {
+ // If the failure is due to a malformed type error, display it instead.
+ if (!malformed_error.IsNull()) {
+ ErrorMsg(malformed_error);
+ } else {
+ ErrorMsg(arg->AsLiteralNode()->token_index(),
+ "map literal value at index %d must be "
+ "a constant of type '%s'",
+ i >> 1,
+ String::Handle(value_type.Name()).ToCString());
+ }
}
key_value_array.SetAt(i, arg->AsLiteralNode()->literal());
}
@@ -7298,6 +7321,9 @@
}
intptr_t type_pos = token_index_;
+ // TODO(regis): Bounds error should not result in a compile time error,
+ // but in a dynamic type error. Requesting kFinalizeWellFormed below is too
+ // strict. See co19 issue 96.
const AbstractType& type = AbstractType::Handle(
ParseType(ClassFinalizer::kFinalizeWellFormed));
if (type.IsTypeParameter()) {
@@ -7375,9 +7401,11 @@
// Only change the class of the constructor to the factory class if the
// factory class implements the interface 'type'.
const Class& factory_class = Class::Handle(type_class.FactoryClass());
+ Error& malformed_error = Error::Handle();
if (factory_class.IsSubtypeOf(TypeArguments::Handle(),
type_class,
- TypeArguments::Handle())) {
+ TypeArguments::Handle(),
+ &malformed_error)) {
// Class finalization verifies that the factory class has identical type
// parameters as the interface.
constructor_class_name = factory_class.Name();
@@ -7481,6 +7509,8 @@
// Make sure that the instantiator is captured.
CaptureReceiver();
}
+ // TODO(regis): If the type argument vector is not instantiated, we need to
+ // verify in checked mode at runtime that it is within its declared bounds.
new_object = new ConstructorCallNode(
new_pos, type_arguments, constructor, arguments);
}

Powered by Google App Engine
This is Rietveld 408576698