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

Print this page

        

@@ -23,10 +23,11 @@
  * questions.
  */
 
 package com.sun.tools.javac.comp;
 
+import com.sun.source.tree.*;
 import com.sun.source.tree.LambdaExpressionTree.BodyKind;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;

@@ -74,10 +75,11 @@
     final Symtab syms;
     final TreeMaker make;
     final Types types;
     final Flow flow;
     final Names names;
+    final Annotate annotate;
 
     public static DeferredAttr instance(Context context) {
         DeferredAttr instance = context.get(deferredAttrKey);
         if (instance == null)
             instance = new DeferredAttr(context);

@@ -97,10 +99,11 @@
         make = TreeMaker.instance(context);
         types = Types.instance(context);
         flow = Flow.instance(context);
         names = Names.instance(context);
         stuckTree = make.Ident(names.empty).setType(Type.stuckType);
+        annotate = Annotate.instance(context);
         emptyDeferredAttrContext =
             new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, infer.emptyContext, null, null) {
                 @Override
                 void addDeferredAttrNode(DeferredType dt, ResultInfo ri, DeferredStuckPolicy deferredStuckPolicy) {
                     Assert.error("Empty deferred context!");

@@ -130,16 +133,23 @@
 
         public JCExpression tree;
         Env<AttrContext> env;
         AttrMode mode;
         SpeculativeCache speculativeCache;
+        final JCLambda currLambda;
+        final Annotate.PositionCreator creator;
 
-        DeferredType(JCExpression tree, Env<AttrContext> env) {
+        DeferredType(JCExpression tree,
+                     Env<AttrContext> env,
+                     JCLambda currLambda,
+                     Annotate.PositionCreator creator) {
             super(null, noAnnotations);
             this.tree = tree;
             this.env = attr.copyEnv(env);
             this.speculativeCache = new SpeculativeCache();
+            this.currLambda = currLambda;
+            this.creator = creator;
         }
 
         @Override
         public DeferredType annotatedType(List<Attribute.TypeCompound> typeAnnotations) {
             throw new AssertionError("Cannot annotate a deferred type");

@@ -275,16 +285,20 @@
             switch (deferredAttrContext.mode) {
                 case SPECULATIVE:
                     //Note: if a symbol is imported twice we might do two identical
                     //speculative rounds...
                     Assert.check(dt.mode == null || dt.mode == AttrMode.SPECULATIVE);
-                    JCTree speculativeTree = attribSpeculative(dt.tree, dt.env, resultInfo);
+                    JCTree speculativeTree = attribSpeculative(dt.tree, dt.env,
+                                                               resultInfo,
+                                                               dt.currLambda,
+                                                               dt.creator);
                     dt.speculativeCache.put(speculativeTree, resultInfo);
                     return speculativeTree.type;
                 case CHECK:
                     Assert.check(dt.mode != null);
-                    return attr.attribTree(dt.tree, dt.env, resultInfo);
+                    return attr.attribTree(dt.tree, dt.env, dt.currLambda,
+                                           resultInfo, false);
             }
             Assert.error();
             return null;
         }
     };

@@ -357,11 +371,15 @@
      * Routine that performs speculative type-checking; the input AST node is
      * cloned (to avoid side-effects cause by Attr) and compiler state is
      * restored after type-checking. All diagnostics (but critical ones) are
      * disabled during speculative type-checking.
      */
-    JCTree attribSpeculative(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) {
+    JCTree attribSpeculative(JCTree tree,
+                             Env<AttrContext> env,
+                             ResultInfo resultInfo,
+                             JCLambda currLambda,
+                             Annotate.PositionCreator creator) {
         final JCTree newTree = new TreeCopier<>(make).copy(tree);
         Env<AttrContext> speculativeEnv = env.dup(newTree, env.info.dup(env.info.scope.dupUnshared()));
         speculativeEnv.info.scope.owner = env.info.scope.owner;
         Log.DeferredDiagnosticHandler deferredDiagnosticHandler =
                 new Log.DeferredDiagnosticHandler(log, new Filter<JCDiagnostic>() {

@@ -382,11 +400,16 @@
                 posScanner.scan(newTree);
                 return posScanner.found;
             }
         });
         try {
-            attr.attribTree(newTree, speculativeEnv, resultInfo);
+            attr.attribTree(newTree, speculativeEnv, currLambda,
+                            resultInfo, true);
+            annotate.typeAnnotateExprLater(newTree, speculativeEnv,
+                                           speculativeEnv.info.scope.owner,
+                                           newTree.pos(), currLambda,
+                                           creator);
             unenterScanner.scan(newTree);
             return newTree;
         } finally {
             unenterScanner.scan(newTree);
             log.popDiagnosticHandler(deferredDiagnosticHandler);

@@ -596,15 +619,17 @@
         class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter {
 
             ResultInfo resultInfo;
             InferenceContext inferenceContext;
             Env<AttrContext> env;
+            JCLambda currLambda;
 
             public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
                 this.resultInfo = resultInfo;
                 this.inferenceContext = deferredAttrContext.inferenceContext;
                 this.env = dt.env;
+                this.currLambda = dt.currLambda;
                 dt.tree.accept(this);
                 dt.speculativeCache.put(stuckTree, resultInfo);
                 return Type.noType;
             }
 

@@ -679,11 +704,15 @@
                     while (tmpParams.nonEmpty()) {
                         tmpParams.head.vartype = make.at(tmpParams.head).Type(syms.errType);
                         tmpParams = tmpParams.tail;
                     }
 
-                    attr.attribStats(newTree.params, localEnv);
+                    int i = 0;
+                    for (List<JCVariableDecl> l = newTree.params;
+                         l.nonEmpty(); l = l.tail, i++) {
+                        attr.attribStat(l.head, tree, localEnv, true);
+                    }
 
                     /* set pt to Type.noType to avoid generating any bound
                      * which may happen if lambda's return type is an
                      * inference variable
                      */

@@ -700,11 +729,11 @@
                          * and the reachability of some statements depends
                          * on constant values, for example:
                          *
                          *     while (true) {...}
                          */
-                        attr.attribStats(body.stats, localEnv);
+                        attr.attribStats(body.stats, tree, localEnv, true);
 
                         attr.preFlow(newTree);
                         /* make an aliveness / reachability analysis of the lambda
                          * to determine if it can complete normally
                          */

@@ -739,12 +768,16 @@
                         types.findDescriptorType(pt);
                     } catch (Types.FunctionDescriptorLookupError ex) {
                         checkContext.report(null, ex.getDiagnostic());
                     }
                     Env<AttrContext> localEnv = env.dup(tree);
-                    JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv,
-                            attr.memberReferenceQualifierResult(tree));
+                    JCExpression exprTree =
+                        (JCExpression)attribSpeculative(tree.getQualifierExpression(),
+                                                        localEnv,
+                                                        attr.memberReferenceQualifierResult(tree),
+                                                        currLambda,
+                                                        annotate.methodRefCreator(tree.pos));
                     ListBuffer<Type> argtypes = new ListBuffer<>();
                     for (Type t : types.findDescriptorType(pt).getParameterTypes()) {
                         argtypes.append(Type.noType);
                     }
                     JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);

@@ -1082,12 +1115,14 @@
     }
 
     /**
      * Does the argument expression {@code expr} need speculative type-checking?
      */
-    boolean isDeferred(Env<AttrContext> env, JCExpression expr) {
-        DeferredChecker dc = new DeferredChecker(env);
+    boolean isDeferred(Env<AttrContext> env,
+                       JCExpression expr,
+                       JCLambda currLambda) {
+        DeferredChecker dc = new DeferredChecker(env, currLambda);
         dc.scan(expr);
         return dc.result.isPoly();
     }
 
     /**

@@ -1144,16 +1179,19 @@
      * Tree scanner used for checking as to whether an argument expression
      * requires speculative attribution
      */
     final class DeferredChecker extends FilterScanner {
 
+        private final JCLambda currLambda;
         Env<AttrContext> env;
         ArgumentExpressionKind result;
 
-        public DeferredChecker(Env<AttrContext> env) {
+        public DeferredChecker(Env<AttrContext> env,
+                               JCLambda currLambda) {
             super(deferredCheckerTags);
             this.env = env;
+            this.currLambda = currLambda;
         }
 
         @Override
         public void visitLambda(JCLambda tree) {
             //a lambda is always a poly expression

@@ -1162,12 +1200,16 @@
 
         @Override
         public void visitReference(JCMemberReference tree) {
             //perform arity-based check
             Env<AttrContext> localEnv = env.dup(tree);
-            JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv,
-                    attr.memberReferenceQualifierResult(tree));
+            JCExpression exprTree =
+                (JCExpression)attribSpeculative(tree.getQualifierExpression(),
+                                                localEnv,
+                                                attr.memberReferenceQualifierResult(tree),
+                                                currLambda,
+                                                annotate.methodRefCreator(tree.pos));
             JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
             mref2.expr = exprTree;
             Symbol res =
                     rs.getMemberReference(tree, localEnv, mref2,
                         exprTree.type, tree.name);

@@ -1230,11 +1272,12 @@
                 result = ArgumentExpressionKind.POLY;
                 return;
             }
 
             Type site = rec != null ?
-                    attribSpeculative(rec, env, attr.unknownTypeExprInfo).type :
+                attribSpeculative(rec, env, attr.unknownTypeExprInfo,
+                                  currLambda, annotate.noCreator).type :
                     env.enclClass.sym.type;
 
             while (site.hasTag(TYPEVAR)) {
                 site = site.getUpperBound();
             }