| Index: runtime/vm/parser.cc
|
| diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
|
| index 6cc8e5421676438b17b07fdde16c095f27fbaeca..58459e093fa6274058d5afb8eaef66fd1c99ede3 100644
|
| --- a/runtime/vm/parser.cc
|
| +++ b/runtime/vm/parser.cc
|
| @@ -3573,7 +3573,7 @@ void Parser::ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method) {
|
| (LookaheadToken(3) == Token::kPERIOD);
|
| const AbstractType& type = AbstractType::Handle(Z,
|
| ParseType(ClassFinalizer::kResolveTypeParameters,
|
| - false, // Deferred types not allowed.
|
| + true,
|
| consume_unresolved_prefix));
|
| if (!type.IsMalformed() && type.IsTypeParameter()) {
|
| // Replace the type with a malformed type and compile a throw when called.
|
| @@ -12019,13 +12019,16 @@ RawAbstractType* Parser::ParseType(
|
| // If deferred prefixes are allowed but it is not yet loaded,
|
| // remember that this function depends on the prefix.
|
| if (allow_deferred_type && !prefix.is_loaded()) {
|
| - ASSERT(parsed_function() != NULL);
|
| - parsed_function()->AddDeferredPrefix(prefix);
|
| + if (parsed_function() != NULL) {
|
| + parsed_function()->AddDeferredPrefix(prefix);
|
| + }
|
| }
|
| - // If the deferred prefixes are not allowed, or if the prefix
|
| - // is not yet loaded, return a malformed type. Otherwise, handle
|
| - // resolution below, as needed.
|
| - if (!prefix.is_loaded() || !allow_deferred_type) {
|
| + // If the deferred prefixes are not allowed, or if the prefix is not yet
|
| + // loaded when finalization is requested, return a malformed type.
|
| + // Otherwise, handle resolution below, as needed.
|
| + if (!allow_deferred_type ||
|
| + (!prefix.is_loaded()
|
| + && (finalization > ClassFinalizer::kResolveTypeParameters))) {
|
| ParseTypeArguments(ClassFinalizer::kIgnore);
|
| return ClassFinalizer::NewFinalizedMalformedType(
|
| Error::Handle(Z), // No previous error.
|
| @@ -12702,6 +12705,28 @@ AstNode* Parser::ParseNewOperator(Token::Kind op_kind) {
|
| String::Handle(Z, redirect_type.UserVisibleName()).ToCString());
|
| }
|
| }
|
| + if (!redirect_type.HasResolvedTypeClass()) {
|
| + // If the redirection type is unresolved, we convert the allocation
|
| + // into throwing a type error.
|
| + const UnresolvedClass& cls =
|
| + UnresolvedClass::Handle(Z, redirect_type.unresolved_class());
|
| + const LibraryPrefix& prefix =
|
| + LibraryPrefix::Handle(Z, cls.library_prefix());
|
| + if (!prefix.IsNull() && !prefix.is_loaded()) {
|
| + // If the redirection type is unresolved because it refers to
|
| + // an unloaded deferred prefix, mark this function as depending
|
| + // on the library prefix. It will then get invalidated when the
|
| + // prefix is loaded.
|
| + parsed_function()->AddDeferredPrefix(prefix);
|
| + }
|
| + redirect_type = ClassFinalizer::NewFinalizedMalformedType(
|
| + Error::Handle(Z),
|
| + script_,
|
| + call_pos,
|
| + "redirection type '%s' is not loaded",
|
| + String::Handle(Z, redirect_type.UserVisibleName()).ToCString());
|
| + }
|
| +
|
| if (redirect_type.IsMalformedOrMalbounded()) {
|
| if (is_const) {
|
| ReportError(Error::Handle(Z, redirect_type.error()));
|
|
|