src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java

changeset 1510
7873d37f5b37
parent 1481
d07340b61e6a
child 1550
1df20330f6bd
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Mon Jan 21 11:16:28 2013 -0800
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Mon Jan 21 20:13:56 2013 +0000
     1.3 @@ -65,6 +65,7 @@
     1.4  
     1.5      final Attr attr;
     1.6      final Check chk;
     1.7 +    final JCDiagnostic.Factory diags;
     1.8      final Enter enter;
     1.9      final Infer infer;
    1.10      final Log log;
    1.11 @@ -83,14 +84,20 @@
    1.12          context.put(deferredAttrKey, this);
    1.13          attr = Attr.instance(context);
    1.14          chk = Check.instance(context);
    1.15 +        diags = JCDiagnostic.Factory.instance(context);
    1.16          enter = Enter.instance(context);
    1.17          infer = Infer.instance(context);
    1.18          log = Log.instance(context);
    1.19          syms = Symtab.instance(context);
    1.20          make = TreeMaker.instance(context);
    1.21          types = Types.instance(context);
    1.22 +        Names names = Names.instance(context);
    1.23 +        stuckTree = make.Ident(names.empty).setType(Type.noType);
    1.24      }
    1.25  
    1.26 +    /** shared tree for stuck expressions */
    1.27 +    final JCTree stuckTree;
    1.28 +
    1.29      /**
    1.30       * This type represents a deferred type. A deferred type starts off with
    1.31       * no information on the underlying expression type. Such info needs to be
    1.32 @@ -356,12 +363,11 @@
    1.33                  //scan a defensive copy of the node list - this is because a deferred
    1.34                  //attribution round can add new nodes to the list
    1.35                  for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) {
    1.36 -                    if (!deferredAttrNode.isStuck()) {
    1.37 -                        deferredAttrNode.process();
    1.38 +                    if (!deferredAttrNode.process()) {
    1.39 +                        stuckVars.addAll(deferredAttrNode.stuckVars);
    1.40 +                    } else {
    1.41                          deferredAttrNodes.remove(deferredAttrNode);
    1.42                          progress = true;
    1.43 -                    } else {
    1.44 -                        stuckVars.addAll(deferredAttrNode.stuckVars);
    1.45                      }
    1.46                  }
    1.47                  if (!progress) {
    1.48 @@ -404,21 +410,88 @@
    1.49              }
    1.50  
    1.51              /**
    1.52 -             * is this node stuck?
    1.53 +             * Process a deferred attribution node.
    1.54 +             * Invariant: a stuck node cannot be processed.
    1.55               */
    1.56 -            boolean isStuck() {
    1.57 -                return stuckVars.nonEmpty();
    1.58 +            @SuppressWarnings("fallthrough")
    1.59 +            boolean process() {
    1.60 +                switch (mode) {
    1.61 +                    case SPECULATIVE:
    1.62 +                        dt.check(resultInfo, List.<Type>nil(), new StructuralStuckChecker());
    1.63 +                        return true;
    1.64 +                    case CHECK:
    1.65 +                        if (stuckVars.nonEmpty()) {
    1.66 +                            return false;
    1.67 +                        } else {
    1.68 +                            dt.check(resultInfo, stuckVars, basicCompleter);
    1.69 +                            return true;
    1.70 +                        }
    1.71 +                    default:
    1.72 +                        throw new AssertionError("Bad mode");
    1.73 +                }
    1.74              }
    1.75  
    1.76              /**
    1.77 -             * Process a deferred attribution node.
    1.78 -             * Invariant: a stuck node cannot be processed.
    1.79 +             * Structural checker for stuck expressions
    1.80               */
    1.81 -            void process() {
    1.82 -                if (isStuck()) {
    1.83 -                    throw new IllegalStateException("Cannot process a stuck deferred node");
    1.84 +            class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter {
    1.85 +
    1.86 +                ResultInfo resultInfo;
    1.87 +
    1.88 +                public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
    1.89 +                    this.resultInfo = resultInfo;
    1.90 +                    dt.tree.accept(this);
    1.91 +                    dt.speculativeCache.put(msym, stuckTree, phase);
    1.92 +                    return Type.noType;
    1.93                  }
    1.94 -                dt.check(resultInfo);
    1.95 +
    1.96 +                @Override
    1.97 +                public void visitLambda(JCLambda tree) {
    1.98 +                    Check.CheckContext checkContext = resultInfo.checkContext;
    1.99 +                    Type pt = resultInfo.pt;
   1.100 +                    if (inferenceContext.inferencevars.contains(pt)) {
   1.101 +                        //ok
   1.102 +                        return;
   1.103 +                    } else {
   1.104 +                        //must be a functional descriptor
   1.105 +                        try {
   1.106 +                            Type desc = types.findDescriptorType(pt);
   1.107 +                            if (desc.getParameterTypes().length() != tree.params.length()) {
   1.108 +                                checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda"));
   1.109 +                            }
   1.110 +                        } catch (Types.FunctionDescriptorLookupError ex) {
   1.111 +                            checkContext.report(null, ex.getDiagnostic());
   1.112 +                        }
   1.113 +                    }
   1.114 +                }
   1.115 +
   1.116 +                @Override
   1.117 +                public void visitNewClass(JCNewClass tree) {
   1.118 +                    //do nothing
   1.119 +                }
   1.120 +
   1.121 +                @Override
   1.122 +                public void visitApply(JCMethodInvocation tree) {
   1.123 +                    //do nothing
   1.124 +                }
   1.125 +
   1.126 +                @Override
   1.127 +                public void visitReference(JCMemberReference tree) {
   1.128 +                    Check.CheckContext checkContext = resultInfo.checkContext;
   1.129 +                    Type pt = resultInfo.pt;
   1.130 +                    if (inferenceContext.inferencevars.contains(pt)) {
   1.131 +                        //ok
   1.132 +                        return;
   1.133 +                    } else {
   1.134 +                        try {
   1.135 +                            //TODO: we should speculative determine if there's a match
   1.136 +                            //based on arity - if yes, method is applicable.
   1.137 +                            types.findDescriptorType(pt);
   1.138 +                        } catch (Types.FunctionDescriptorLookupError ex) {
   1.139 +                            checkContext.report(null, ex.getDiagnostic());
   1.140 +                        }
   1.141 +                    }
   1.142 +                }
   1.143              }
   1.144          }
   1.145      }
   1.146 @@ -624,12 +697,12 @@
   1.147              if (inferenceContext.inferenceVars().contains(pt)) {
   1.148                  stuckVars.add(pt);
   1.149              }
   1.150 -            if (!types.isFunctionalInterface(pt.tsym)) {
   1.151 +            if (!types.isFunctionalInterface(pt)) {
   1.152                  return;
   1.153              }
   1.154              Type descType = types.findDescriptorType(pt);
   1.155              List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
   1.156 -            if (!TreeInfo.isExplicitLambda(tree) &&
   1.157 +            if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT &&
   1.158                      freeArgVars.nonEmpty()) {
   1.159                  stuckVars.addAll(freeArgVars);
   1.160              }
   1.161 @@ -643,7 +716,7 @@
   1.162                  stuckVars.add(pt);
   1.163                  return;
   1.164              }
   1.165 -            if (!types.isFunctionalInterface(pt.tsym)) {
   1.166 +            if (!types.isFunctionalInterface(pt)) {
   1.167                  return;
   1.168              }
   1.169  

mercurial