| Index: runtime/vm/parser.cc
|
| ===================================================================
|
| --- runtime/vm/parser.cc (revision 25651)
|
| +++ runtime/vm/parser.cc (working copy)
|
| @@ -29,6 +29,7 @@
|
| DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations.");
|
| DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors.");
|
| DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings.");
|
| +DECLARE_FLAG(bool, error_on_malformed_type);
|
| DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
|
|
|
| static void CheckedModeHandler(bool value) {
|
| @@ -2934,7 +2935,6 @@
|
| Error::Handle(), // No previous error.
|
| current_class(),
|
| type_pos,
|
| - ClassFinalizer::kResolveTypeParameters, // No compile-time error.
|
| "factory '%s' may not redirect to type parameter '%s'",
|
| method->name->ToCString(),
|
| String::Handle(type.UserVisibleName()).ToCString());
|
| @@ -4119,7 +4119,6 @@
|
|
|
|
|
| RawAbstractTypeArguments* Parser::ParseTypeArguments(
|
| - Error* malformed_error,
|
| ClassFinalizer::FinalizationKind finalization) {
|
| TRACE_PARSER("ParseTypeArguments");
|
| if (CurrentToken() == Token::kLT) {
|
| @@ -4129,14 +4128,8 @@
|
| do {
|
| ConsumeToken();
|
| type = ParseType(finalization);
|
| - // Only keep the error for the first malformed type argument.
|
| - if (malformed_error->IsNull() && type.IsMalformed()) {
|
| - *malformed_error = type.malformed_error();
|
| - }
|
| - // Map a malformed type argument to dynamic, so that malformed types with
|
| - // a resolved type class are handled properly in production mode.
|
| + // Map a malformed type argument to dynamic.
|
| if (type.IsMalformed()) {
|
| - ASSERT(finalization < ClassFinalizer::kCanonicalizeWellFormed);
|
| type = Type::DynamicType();
|
| }
|
| types.Add(type);
|
| @@ -6430,10 +6423,8 @@
|
| catch_seen = true;
|
| if (IsLiteral("on")) {
|
| ConsumeToken();
|
| - // TODO(regis): The spec may change in the way a malformed 'on' type is
|
| - // treated. For now, we require the type to be wellformed.
|
| exception_param.type = &AbstractType::ZoneHandle(
|
| - ParseType(ClassFinalizer::kCanonicalizeWellFormed));
|
| + ParseType(ClassFinalizer::kCanonicalize));
|
| } else {
|
| exception_param.type =
|
| &AbstractType::ZoneHandle(Type::DynamicType());
|
| @@ -7141,13 +7132,15 @@
|
| }
|
| const intptr_t type_pos = TokenPos();
|
| const AbstractType& type = AbstractType::ZoneHandle(
|
| - ParseType(ClassFinalizer::kCanonicalizeExpression));
|
| + ParseType(ClassFinalizer::kCanonicalize));
|
| if (!type.IsInstantiated() &&
|
| (current_block_->scope->function_level() > 0)) {
|
| // Make sure that the instantiator is captured.
|
| CaptureInstantiator();
|
| }
|
| right_operand = new TypeNode(type_pos, type);
|
| + // If the type is malformed, it is actually malbounded in checked mode.
|
| + ASSERT(!type.IsMalformed() || FLAG_enable_type_checks);
|
| if (((op_kind == Token::kIS) || (op_kind == Token::kISNOT)) &&
|
| type.IsMalformed()) {
|
| // Note that a type error is thrown even if the tested value is null
|
| @@ -8159,26 +8152,36 @@
|
| // referenced by a static member.
|
| if (ParsingStaticMember()) {
|
| ASSERT(scope_class.raw() == current_class().raw());
|
| - *type = ClassFinalizer::NewFinalizedMalformedType(
|
| - Error::Handle(), // No previous error.
|
| - scope_class,
|
| - type->token_pos(),
|
| - finalization,
|
| - "type parameter '%s' cannot be referenced "
|
| - "from static member",
|
| - String::Handle(type_parameter.name()).ToCString());
|
| + if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
|
| + FLAG_error_on_malformed_type) {
|
| + *type = ClassFinalizer::NewFinalizedMalformedType(
|
| + Error::Handle(), // No previous error.
|
| + scope_class,
|
| + type->token_pos(),
|
| + "type parameter '%s' cannot be referenced "
|
| + "from static member",
|
| + String::Handle(type_parameter.name()).ToCString());
|
| + } else {
|
| + // Map the malformed type to dynamic and ignore type arguments.
|
| + *type = Type::DynamicType();
|
| + }
|
| return;
|
| }
|
| // A type parameter cannot be parameterized, so make the type
|
| // malformed if type arguments have previously been parsed.
|
| if (!AbstractTypeArguments::Handle(type->arguments()).IsNull()) {
|
| - *type = ClassFinalizer::NewFinalizedMalformedType(
|
| - Error::Handle(), // No previous error.
|
| - scope_class,
|
| - type_parameter.token_pos(),
|
| - finalization,
|
| - "type parameter '%s' cannot be parameterized",
|
| - String::Handle(type_parameter.name()).ToCString());
|
| + if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
|
| + FLAG_error_on_malformed_type) {
|
| + *type = ClassFinalizer::NewFinalizedMalformedType(
|
| + Error::Handle(), // No previous error.
|
| + scope_class,
|
| + type_parameter.token_pos(),
|
| + "type parameter '%s' cannot be parameterized",
|
| + String::Handle(type_parameter.name()).ToCString());
|
| + } else {
|
| + // Map the malformed type to dynamic and ignore type arguments.
|
| + *type = Type::DynamicType();
|
| + }
|
| return;
|
| }
|
| *type = type_parameter.raw();
|
| @@ -8190,22 +8193,23 @@
|
| 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(),
|
| unresolved_class_name,
|
| - finalization >= ClassFinalizer::kCanonicalizeExpression ?
|
| - NULL : &error);
|
| + &error);
|
| if (!error.IsNull()) {
|
| - *type = ClassFinalizer::NewFinalizedMalformedType(
|
| - error,
|
| - scope_class,
|
| - unresolved_class.token_pos(),
|
| - finalization,
|
| - "cannot resolve class '%s'",
|
| - unresolved_class_name.ToCString());
|
| + if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
|
| + FLAG_error_on_malformed_type) {
|
| + *type = ClassFinalizer::NewFinalizedMalformedType(
|
| + error,
|
| + scope_class,
|
| + unresolved_class.token_pos(),
|
| + "cannot resolve class '%s'",
|
| + unresolved_class_name.ToCString());
|
| + } else {
|
| + // Map the malformed type to dynamic and ignore type arguments.
|
| + *type = Type::DynamicType();
|
| + }
|
| return;
|
| }
|
| }
|
| @@ -8214,39 +8218,46 @@
|
| LibraryPrefix::Handle(unresolved_class.library_prefix());
|
| // Resolve class name in the scope of the library prefix.
|
| 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 = ResolveClassInPrefixScope(
|
| unresolved_class.token_pos(),
|
| lib_prefix,
|
| unresolved_class_name,
|
| - finalization >= ClassFinalizer::kCanonicalizeExpression ?
|
| - NULL : &error);
|
| + &error);
|
| if (!error.IsNull()) {
|
| - *type = ClassFinalizer::NewFinalizedMalformedType(
|
| - error,
|
| - scope_class,
|
| - unresolved_class.token_pos(),
|
| - finalization,
|
| - "cannot resolve class '%s'",
|
| - unresolved_class_name.ToCString());
|
| + if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
|
| + FLAG_error_on_malformed_type) {
|
| + *type = ClassFinalizer::NewFinalizedMalformedType(
|
| + error,
|
| + scope_class,
|
| + unresolved_class.token_pos(),
|
| + "cannot resolve class '%s'",
|
| + unresolved_class_name.ToCString());
|
| + } else {
|
| + // Map the malformed type to dynamic and ignore type arguments.
|
| + *type = Type::DynamicType();
|
| + }
|
| return;
|
| }
|
| }
|
| // At this point, we can only have a parameterized_type.
|
| - Type& parameterized_type = Type::Handle();
|
| - parameterized_type ^= type->raw();
|
| + const Type& parameterized_type = Type::Cast(*type);
|
| if (!resolved_type_class.IsNull()) {
|
| // Replace unresolved class with resolved type class.
|
| parameterized_type.set_type_class(resolved_type_class);
|
| } else if (finalization >= ClassFinalizer::kCanonicalize) {
|
| - // 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.UserVisibleName()).ToCString());
|
| + if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
|
| + FLAG_error_on_malformed_type) {
|
| + ClassFinalizer::FinalizeMalformedType(
|
| + Error::Handle(), // No previous error.
|
| + scope_class,
|
| + parameterized_type,
|
| + "type '%s' is not loaded",
|
| + String::Handle(parameterized_type.UserVisibleName()).ToCString());
|
| + } else {
|
| + // Map the malformed type to dynamic and ignore type arguments.
|
| + *type = Type::DynamicType();
|
| + }
|
| + return;
|
| }
|
| }
|
| // Resolve type arguments, if any.
|
| @@ -8954,8 +8965,17 @@
|
| if (!is_top_level_ &&
|
| (type_name.lib_prefix == NULL) &&
|
| ResolveIdentInLocalScope(type_name.ident_pos, *type_name.ident, NULL)) {
|
| - ErrorMsg(type_name.ident_pos, "using '%s' in this context is invalid",
|
| - type_name.ident->ToCString());
|
| + // The type is malformed. Skip over its type arguments.
|
| + ParseTypeArguments(ClassFinalizer::kIgnore);
|
| + if (finalization == ClassFinalizer::kCanonicalizeWellFormed) {
|
| + return ClassFinalizer::NewFinalizedMalformedType(
|
| + Error::Handle(), // No previous error.
|
| + current_class(),
|
| + type_name.ident_pos,
|
| + "using '%s' in this context is invalid",
|
| + type_name.ident->ToCString());
|
| + }
|
| + return Type::DynamicType();
|
| }
|
| }
|
| Object& type_class = Object::Handle(isolate());
|
| @@ -8969,27 +8989,13 @@
|
| *type_name.ident,
|
| type_name.ident_pos);
|
| }
|
| - Error& malformed_error = Error::Handle(isolate());
|
| - AbstractTypeArguments& type_arguments =
|
| - AbstractTypeArguments::Handle(isolate(),
|
| - ParseTypeArguments(&malformed_error,
|
| - finalization));
|
| + AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle(
|
| + isolate(), ParseTypeArguments(finalization));
|
| if (finalization == ClassFinalizer::kIgnore) {
|
| return Type::DynamicType();
|
| }
|
| AbstractType& type = AbstractType::Handle(
|
| - isolate(),
|
| - Type::New(type_class, type_arguments, type_name.ident_pos));
|
| - // In production mode, malformed type arguments are mapped to dynamic.
|
| - // In checked mode, a type with malformed type arguments is malformed.
|
| - if (FLAG_enable_type_checks && !malformed_error.IsNull()) {
|
| - Type& parameterized_type = Type::Handle(isolate());
|
| - parameterized_type ^= type.raw();
|
| - parameterized_type.set_type_class(
|
| - Class::Handle(isolate(), Object::dynamic_class()));
|
| - parameterized_type.set_arguments(Object::null_abstract_type_arguments());
|
| - parameterized_type.set_malformed_error(malformed_error);
|
| - }
|
| + isolate(), Type::New(type_class, type_arguments, type_name.ident_pos));
|
| if (finalization >= ClassFinalizer::kResolveTypeParameters) {
|
| ResolveTypeFromClass(current_class(), finalization, &type);
|
| if (finalization >= ClassFinalizer::kCanonicalize) {
|
| @@ -9031,16 +9037,23 @@
|
| ConsumeToken();
|
|
|
| AbstractType& element_type = Type::ZoneHandle(Type::DynamicType());
|
| + AbstractTypeArguments& list_type_arguments =
|
| + AbstractTypeArguments::ZoneHandle(type_arguments.raw());
|
| // If no type argument vector is provided, leave it as null, which is
|
| // equivalent to using dynamic as the type argument for the element type.
|
| - if (!type_arguments.IsNull()) {
|
| - ASSERT(type_arguments.Length() > 0);
|
| + if (!list_type_arguments.IsNull()) {
|
| + ASSERT(list_type_arguments.Length() > 0);
|
| // List literals take a single type argument.
|
| - element_type = type_arguments.TypeAt(0);
|
| - if (type_arguments.Length() != 1) {
|
| - ErrorMsg(type_pos,
|
| - "a list literal takes one type argument specifying "
|
| - "the element type");
|
| + if (list_type_arguments.Length() == 1) {
|
| + element_type = list_type_arguments.TypeAt(0);
|
| + } else {
|
| + if (FLAG_error_on_malformed_type) {
|
| + ErrorMsg(type_pos,
|
| + "a list literal takes one type argument specifying "
|
| + "the element type");
|
| + }
|
| + // Ignore type arguments.
|
| + list_type_arguments = AbstractTypeArguments::null();
|
| }
|
| if (is_const && !element_type.IsInstantiated()) {
|
| ErrorMsg(type_pos,
|
| @@ -9048,11 +9061,12 @@
|
| "a type variable");
|
| }
|
| }
|
| - ASSERT(type_arguments.IsNull() || (type_arguments.Length() == 1));
|
| + ASSERT((list_type_arguments.IsNull() && element_type.IsDynamicType()) ||
|
| + ((list_type_arguments.Length() == 1) && !element_type.IsNull()));
|
| const Class& array_class = Class::Handle(
|
| isolate()->object_store()->array_class());
|
| Type& type = Type::ZoneHandle(
|
| - Type::New(array_class, type_arguments, type_pos));
|
| + Type::New(array_class, list_type_arguments, type_pos));
|
| type ^= ClassFinalizer::FinalizeType(
|
| current_class(), type, ClassFinalizer::kCanonicalize);
|
| GrowableArray<AstNode*> element_list;
|
| @@ -9087,7 +9101,7 @@
|
| Array& const_list =
|
| Array::ZoneHandle(Array::New(element_list.length(), Heap::kOld));
|
| const_list.SetTypeArguments(
|
| - AbstractTypeArguments::Handle(type_arguments.Canonicalize()));
|
| + AbstractTypeArguments::Handle(list_type_arguments.Canonicalize()));
|
| Error& malformed_error = Error::Handle();
|
| for (int i = 0; i < element_list.length(); i++) {
|
| AstNode* elem = element_list[i];
|
| @@ -9124,14 +9138,14 @@
|
| factory_class.LookupFactory(
|
| PrivateCoreLibName(Symbols::ListLiteralFactory())));
|
| ASSERT(!factory_method.IsNull());
|
| - if (!type_arguments.IsNull() &&
|
| - !type_arguments.IsInstantiated() &&
|
| + if (!list_type_arguments.IsNull() &&
|
| + !list_type_arguments.IsInstantiated() &&
|
| (current_block_->scope->function_level() > 0)) {
|
| // Make sure that the instantiator is captured.
|
| CaptureInstantiator();
|
| }
|
| AbstractTypeArguments& factory_type_args =
|
| - AbstractTypeArguments::ZoneHandle(type_arguments.raw());
|
| + AbstractTypeArguments::ZoneHandle(list_type_arguments.raw());
|
| // If the factory class extends other parameterized classes, adjust the
|
| // type argument vector.
|
| if (!factory_type_args.IsNull() && (factory_class.NumTypeArguments() > 1)) {
|
| @@ -9212,49 +9226,72 @@
|
| const intptr_t literal_pos = TokenPos();
|
| ConsumeToken();
|
|
|
| + AbstractType& key_type = Type::ZoneHandle(Type::DynamicType());
|
| AbstractType& value_type = Type::ZoneHandle(Type::DynamicType());
|
| AbstractTypeArguments& map_type_arguments =
|
| AbstractTypeArguments::ZoneHandle(type_arguments.raw());
|
| // If no type argument vector is provided, leave it as null, which is
|
| - // equivalent to using dynamic as the type argument for the value type.
|
| + // equivalent to using dynamic as the type argument for the both key and value
|
| + // types.
|
| if (!map_type_arguments.IsNull()) {
|
| ASSERT(map_type_arguments.Length() > 0);
|
| // Map literals take two type arguments.
|
| - if (map_type_arguments.Length() != 2) {
|
| - ErrorMsg(type_pos,
|
| - "a map literal takes two type arguments specifying "
|
| - "the key type and the value type");
|
| + if (map_type_arguments.Length() == 2) {
|
| + key_type = map_type_arguments.TypeAt(0);
|
| + value_type = map_type_arguments.TypeAt(1);
|
| + if (is_const && !type_arguments.IsInstantiated()) {
|
| + ErrorMsg(type_pos,
|
| + "the type arguments of a constant map literal cannot include "
|
| + "a type variable");
|
| + }
|
| + if (key_type.IsMalformed()) {
|
| + if (FLAG_error_on_malformed_type) {
|
| + ErrorMsg(Error::Handle(key_type.malformed_error()));
|
| + }
|
| + // Map malformed key type to dynamic.
|
| + key_type = Type::DynamicType();
|
| + map_type_arguments.SetTypeAt(0, key_type);
|
| + }
|
| + if (value_type.IsMalformed()) {
|
| + if (FLAG_error_on_malformed_type) {
|
| + ErrorMsg(Error::Handle(value_type.malformed_error()));
|
| + }
|
| + // Map malformed value type to dynamic.
|
| + value_type = Type::DynamicType();
|
| + map_type_arguments.SetTypeAt(1, value_type);
|
| + }
|
| + } else {
|
| + if (FLAG_error_on_malformed_type) {
|
| + ErrorMsg(type_pos,
|
| + "a map literal takes two type arguments specifying "
|
| + "the key type and the value type");
|
| + }
|
| + // Ignore type arguments.
|
| + map_type_arguments = AbstractTypeArguments::null();
|
| }
|
| - const AbstractType& key_type =
|
| - AbstractType::Handle(map_type_arguments.TypeAt(0));
|
| - value_type = map_type_arguments.TypeAt(1);
|
| - if (!key_type.IsStringType()) {
|
| - ErrorMsg(type_pos, "the key type of a map literal must be 'String'");
|
| - }
|
| - if (is_const && !value_type.IsInstantiated()) {
|
| - ErrorMsg(type_pos,
|
| - "the type argument of a constant map literal cannot include "
|
| - "a type variable");
|
| - }
|
| }
|
| - ASSERT(map_type_arguments.IsNull() || (map_type_arguments.Length() == 2));
|
| + ASSERT((map_type_arguments.IsNull() &&
|
| + key_type.IsDynamicType() && value_type.IsDynamicType()) ||
|
| + ((map_type_arguments.Length() == 2) &&
|
| + !key_type.IsMalformed() && !value_type.IsMalformed()));
|
| map_type_arguments ^= map_type_arguments.Canonicalize();
|
|
|
| GrowableArray<AstNode*> kv_pairs_list;
|
| // Parse the map entries. Note: there may be an optional extra
|
| // comma after the last entry.
|
| while (CurrentToken() != Token::kRBRACE) {
|
| - AstNode* key = NULL;
|
| - if (CurrentToken() == Token::kSTRING) {
|
| - key = ParseStringLiteral();
|
| + const bool saved_mode = SetAllowFunctionLiterals(true);
|
| + const intptr_t key_pos = TokenPos();
|
| + AstNode* key = ParseExpr(is_const, kConsumeCascades);
|
| + if (FLAG_enable_type_checks &&
|
| + !is_const &&
|
| + !key_type.IsDynamicType()) {
|
| + key = new AssignableNode(key_pos,
|
| + key,
|
| + key_type,
|
| + Symbols::ListLiteralElement());
|
| }
|
| - if (key == NULL) {
|
| - ErrorMsg("map entry key must be string literal");
|
| - } else if (is_const && !key->IsLiteralNode()) {
|
| - ErrorMsg("map entry key must be compile-time constant string");
|
| - }
|
| ExpectToken(Token::kCOLON);
|
| - const bool saved_mode = SetAllowFunctionLiterals(true);
|
| const intptr_t value_pos = TokenPos();
|
| AstNode* value = ParseExpr(is_const, kConsumeCascades);
|
| SetAllowFunctionLiterals(saved_mode);
|
| @@ -9285,28 +9322,39 @@
|
| // First, create the canonicalized key-value pair array.
|
| Array& key_value_array =
|
| Array::ZoneHandle(Array::New(kv_pairs_list.length(), Heap::kOld));
|
| + AbstractType& arg_type = Type::Handle();
|
| Error& malformed_error = Error::Handle();
|
| for (int i = 0; i < kv_pairs_list.length(); i++) {
|
| AstNode* arg = kv_pairs_list[i];
|
| // Arguments have been evaluated to a literal value already.
|
| ASSERT(arg->IsLiteralNode());
|
| ASSERT(!is_top_level_); // We cannot check unresolved types.
|
| - if (FLAG_enable_type_checks &&
|
| - ((i % 2) == 1) && // Check values only, not keys.
|
| - !value_type.IsDynamicType() &&
|
| - (!arg->AsLiteralNode()->literal().IsNull() &&
|
| - !arg->AsLiteralNode()->literal().IsInstanceOf(
|
| - 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);
|
| + if (FLAG_enable_type_checks) {
|
| + if ((i % 2) == 0) {
|
| + // Check key type.
|
| + arg_type = key_type.raw();
|
| } else {
|
| - ErrorMsg(arg->AsLiteralNode()->token_pos(),
|
| - "map literal value at index %d must be "
|
| - "a constant of type '%s'",
|
| - i >> 1,
|
| - String::Handle(value_type.UserVisibleName()).ToCString());
|
| + // Check value type.
|
| + arg_type = value_type.raw();
|
| }
|
| + if (!arg_type.IsDynamicType() &&
|
| + (!arg->AsLiteralNode()->literal().IsNull() &&
|
| + !arg->AsLiteralNode()->literal().IsInstanceOf(
|
| + arg_type,
|
| + Object::null_abstract_type_arguments(),
|
| + &malformed_error))) {
|
| + // If the failure is due to a malformed type error, display it.
|
| + if (!malformed_error.IsNull()) {
|
| + ErrorMsg(malformed_error);
|
| + } else {
|
| + ErrorMsg(arg->AsLiteralNode()->token_pos(),
|
| + "map literal %s at index %d must be "
|
| + "a constant of type '%s'",
|
| + ((i % 2) == 0) ? "key" : "value",
|
| + i >> 1,
|
| + String::Handle(arg_type.UserVisibleName()).ToCString());
|
| + }
|
| + }
|
| }
|
| key_value_array.SetAt(i, arg->AsLiteralNode()->literal());
|
| }
|
| @@ -9391,15 +9439,10 @@
|
| ConsumeToken();
|
| }
|
| const intptr_t type_pos = TokenPos();
|
| - Error& malformed_error = Error::Handle();
|
| - AbstractTypeArguments& type_arguments = AbstractTypeArguments::ZoneHandle(
|
| - ParseTypeArguments(&malformed_error,
|
| - ClassFinalizer::kCanonicalizeWellFormed));
|
| + AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle(
|
| + ParseTypeArguments(ClassFinalizer::kCanonicalize));
|
| // Map and List interfaces do not declare bounds on their type parameters, so
|
| - // we should never see a malformed type error here.
|
| - // Note that a bound error is the only possible malformed type error returned
|
| - // when requesting kCanonicalizeWellFormed type finalization.
|
| - ASSERT(malformed_error.IsNull());
|
| + // we should never see a malformed type argument mapped to dynamic here.
|
| AstNode* primary = NULL;
|
| if ((CurrentToken() == Token::kLBRACK) ||
|
| (CurrentToken() == Token::kINDEX)) {
|
| @@ -9438,7 +9481,7 @@
|
| }
|
| intptr_t type_pos = TokenPos();
|
| AbstractType& type = AbstractType::Handle(
|
| - ParseType(ClassFinalizer::kCanonicalizeExpression));
|
| + ParseType(ClassFinalizer::kCanonicalizeWellFormed));
|
| // In case the type is malformed, throw a dynamic type error after finishing
|
| // parsing the instance creation expression.
|
| if (!type.IsMalformed() && (type.IsTypeParameter() || type.IsDynamicType())) {
|
| @@ -9447,7 +9490,6 @@
|
| Error::Handle(), // No previous error.
|
| current_class(),
|
| type_pos,
|
| - ClassFinalizer::kResolveTypeParameters, // No compile-time error.
|
| "%s'%s' cannot be instantiated",
|
| type.IsTypeParameter() ? "type parameter " : "",
|
| type.IsTypeParameter() ?
|
| @@ -9455,9 +9497,9 @@
|
| }
|
|
|
| // 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
|
| - // valid library prefix is accepted as qualifier.
|
| + // is a named constructor. Note that ParseType() above will not consume it as
|
| + // part of a misinterpreted qualified identifier, because only a valid library
|
| + // prefix is accepted as qualifier.
|
| String* named_constructor = NULL;
|
| if (CurrentToken() == Token::kPERIOD) {
|
| ConsumeToken();
|
| @@ -9513,7 +9555,6 @@
|
| Error::Handle(), // No previous error.
|
| current_class(),
|
| call_pos,
|
| - 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());
|
| @@ -9633,7 +9674,6 @@
|
| malformed_error,
|
| current_class(),
|
| new_pos,
|
| - 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);
|
|
|