| Index: sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| index 2f79c0cd536da9eeef2b6c1f14244afcd81af69a..1ebc7109cef5b0c72cf723b88ccd8b9772ae05cf 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
|
| @@ -1083,9 +1083,9 @@ class TypeResolver {
|
| DartType type;
|
| if (element == null) {
|
| onFailure(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]);
|
| - } else if (element.isErroneous()) {
|
| - ErroneousElement error = element;
|
| - onFailure(node, error.messageKind, error.messageArguments);
|
| + } else if (element.isAmbiguous()) {
|
| + AmbiguousElement ambiguous = element;
|
| + onFailure(node, ambiguous.messageKind, ambiguous.messageArguments);
|
| } else if (!element.impliesType()) {
|
| onFailure(node, MessageKind.NOT_A_TYPE, [node.typeName]);
|
| } else {
|
| @@ -1199,8 +1199,19 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
|
|
| Element lookup(Node node, SourceString name) {
|
| Element result = scope.lookup(name);
|
| - if (!inInstanceContext && result != null && result.isInstanceMember()) {
|
| - error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]);
|
| + if (!Elements.isUnresolved(result)) {
|
| + if (!inInstanceContext && result.isInstanceMember()) {
|
| + error(node, MessageKind.NO_INSTANCE_AVAILABLE, [node]);
|
| + // TODO(johnniwinther): Create an ErroneousElement.
|
| + } else if (result.isAmbiguous()) {
|
| + AmbiguousElement ambiguous = result;
|
| + compiler.reportMessage(compiler.spanFromNode(node),
|
| + ambiguous.messageKind.error(ambiguous.messageArguments),
|
| + Diagnostic.ERROR);
|
| + return new ErroneousElement(ambiguous.messageKind,
|
| + ambiguous.messageArguments,
|
| + name, enclosingElement);
|
| + }
|
| }
|
| return result;
|
| }
|
| @@ -1241,17 +1252,9 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| SourceString name,
|
| MessageKind kind,
|
| List<Node> arguments) {
|
| - return warnOnErroneousElement(node,
|
| - new ErroneousElement(kind, arguments, name, enclosingElement));
|
| - }
|
| -
|
| - ErroneousElement warnOnErroneousElement(Node node,
|
| - ErroneousElement erroneousElement) {
|
| - ResolutionWarning warning =
|
| - new ResolutionWarning(erroneousElement.messageKind,
|
| - erroneousElement.messageArguments);
|
| + ResolutionWarning warning = new ResolutionWarning(kind, arguments);
|
| compiler.reportWarning(node, warning);
|
| - return erroneousElement;
|
| + return new ErroneousElement(kind, arguments, name, enclosingElement);
|
| }
|
|
|
| Element visitIdentifier(Identifier node) {
|
| @@ -1275,7 +1278,7 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| [node]);
|
| }
|
| } else if (element.isErroneous()) {
|
| - element = warnOnErroneousElement(node, element);
|
| + // Use the erroneous element.
|
| } else {
|
| if ((element.kind.category & allowedCategory) == 0) {
|
| // TODO(ahe): Improve error message. Need UX input.
|
| @@ -1875,9 +1878,38 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
|
|
| visitReturn(Return node) {
|
| if (node.isRedirectingFactoryBody) {
|
| - unimplemented(node, 'redirecting constructors');
|
| + handleRedirectingFactoryBody(node);
|
| + } else {
|
| + visit(node.expression);
|
| }
|
| - visit(node.expression);
|
| + }
|
| +
|
| + void handleRedirectingFactoryBody(Return node) {
|
| + Element redirectionTarget = resolveRedirectingFactory(node);
|
| + var type = mapping.getType(node.expression);
|
| + if (type is InterfaceType && !type.arguments.isEmpty) {
|
| + unimplemented(node.expression, 'type arguments on redirecting factory');
|
| + }
|
| + useElement(node.expression, redirectionTarget);
|
| + assert(invariant(node, enclosingElement.isFactoryConstructor()));
|
| + FunctionElement constructor = enclosingElement;
|
| + if (constructor.modifiers.isConst() &&
|
| + !redirectionTarget.modifiers.isConst()) {
|
| + error(node, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
|
| + }
|
| + // TODO(ahe): Check that this doesn't lead to a cycle. For now,
|
| + // just make sure that the redirection target isn't itself a
|
| + // redirecting factory.
|
| + { // This entire block is temporary code per the above TODO.
|
| + FunctionElement targetImplementation = redirectionTarget.implementation;
|
| + FunctionExpression function = targetImplementation.parseNode(compiler);
|
| + if (function.body != null && function.body.asReturn() != null
|
| + && function.body.asReturn().isRedirectingFactoryBody) {
|
| + unimplemented(node.expression, 'redirecing to redirecting factory');
|
| + }
|
| + }
|
| + constructor.defaultImplementation = redirectionTarget;
|
| + world.registerStaticUse(redirectionTarget);
|
| }
|
|
|
| visitThrow(Throw node) {
|
| @@ -1951,6 +1983,10 @@ class ResolverVisitor extends CommonResolverVisitor<Element> {
|
| return node.accept(new ConstructorResolver(compiler, this));
|
| }
|
|
|
| + FunctionElement resolveRedirectingFactory(Return node) {
|
| + return node.accept(new ConstructorResolver(compiler, this));
|
| + }
|
| +
|
| DartType resolveTypeRequired(TypeAnnotation node) {
|
| bool old = typeRequired;
|
| typeRequired = true;
|
| @@ -2903,8 +2939,7 @@ class ConstructorResolver extends CommonResolverVisitor<Element> {
|
| } else {
|
| ResolutionWarning warning = new ResolutionWarning(kind, arguments);
|
| compiler.reportWarning(diagnosticNode, warning);
|
| - return new ErroneousFunctionElement(kind, arguments, targetName,
|
| - enclosing);
|
| + return new ErroneousElement(kind, arguments, targetName, enclosing);
|
| }
|
| }
|
|
|
| @@ -2945,13 +2980,27 @@ class ConstructorResolver extends CommonResolverVisitor<Element> {
|
| inConstContext = node.isConst();
|
| Node selector = node.send.selector;
|
| Element e = visit(selector);
|
| - if (!Elements.isUnresolved(e) && identical(e.kind, ElementKind.CLASS)) {
|
| + return finishConstructorReference(e, node.send.selector, node);
|
| + }
|
| +
|
| + /// Finishes resolution of a constructor reference and records the
|
| + /// type of the constructed instance on [expression].
|
| + FunctionElement finishConstructorReference(Element e,
|
| + Node diagnosticNode,
|
| + Node expression) {
|
| + // Find the unnamed constructor if the reference resolved to a
|
| + // class.
|
| + if (!Elements.isUnresolved(e) && e.isClass()) {
|
| ClassElement cls = e;
|
| cls.ensureResolved(compiler);
|
| if (cls.isInterface() && (cls.defaultClass == null)) {
|
| - error(selector, MessageKind.CANNOT_INSTANTIATE_INTERFACE, [cls.name]);
|
| + // TODO(ahe): Remove this check and error message when we
|
| + // don't have interfaces anymore.
|
| + error(diagnosticNode,
|
| + MessageKind.CANNOT_INSTANTIATE_INTERFACE, [cls.name]);
|
| }
|
| - e = lookupConstructor(cls, selector, const SourceString(''));
|
| + // The unnamed constructor may not exist, so [e] may become unresolved.
|
| + e = lookupConstructor(cls, diagnosticNode, const SourceString(''));
|
| }
|
| if (type == null) {
|
| if (Elements.isUnresolved(e)) {
|
| @@ -2960,7 +3009,7 @@ class ConstructorResolver extends CommonResolverVisitor<Element> {
|
| type = e.getEnclosingClass().computeType(compiler).asRaw();
|
| }
|
| }
|
| - resolver.mapping.setType(node, type);
|
| + resolver.mapping.setType(expression, type);
|
| return e;
|
| }
|
|
|
| @@ -3008,6 +3057,8 @@ class ConstructorResolver extends CommonResolverVisitor<Element> {
|
| if (e == null) {
|
| return failOrReturnErroneousElement(resolver.enclosingElement, node, name,
|
| MessageKind.CANNOT_RESOLVE, [name]);
|
| + } else if (e.isErroneous()) {
|
| + return e;
|
| } else if (identical(e.kind, ElementKind.TYPEDEF)) {
|
| error(node, MessageKind.CANNOT_INSTANTIATE_TYPEDEF, [name]);
|
| } else if (identical(e.kind, ElementKind.TYPE_VARIABLE)) {
|
| @@ -3018,4 +3069,11 @@ class ConstructorResolver extends CommonResolverVisitor<Element> {
|
| }
|
| return e;
|
| }
|
| +
|
| + /// Assumed to be called by [resolveRedirectingFactory].
|
| + Element visitReturn(Return node) {
|
| + Node expression = node.expression;
|
| + return finishConstructorReference(visit(expression),
|
| + expression, expression);
|
| + }
|
| }
|
|
|