| 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);
|
| }
|
|
|