changeset 1862:8cdd96f2fdb9

8007479: Refactor DeferredAttrContext so that it points to parent context Summary: Move DeferredAttrNode out of DeferredAttrContext; add support for nested deferred contexts Reviewed-by: jjg
author mcimadamore
date Wed, 06 Feb 2013 14:04:43 +0000
parents 1df20330f6bd
children 153d20d0cac5
files src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java src/share/classes/com/sun/tools/javac/comp/Infer.java src/share/classes/com/sun/tools/javac/comp/Resolve.java
diffstat 3 files changed, 116 insertions(+), 104 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Wed Feb 06 14:03:39 2013 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Wed Feb 06 14:04:43 2013 +0000
@@ -332,13 +332,22 @@
         /** inference context */
         final InferenceContext inferenceContext;
 
+        /** parent deferred context */
+        final DeferredAttrContext parent;
+
+        /** Warner object to report warnings */
+        final Warner warn;
+
         /** list of deferred attribution nodes to be processed */
         ArrayList<DeferredAttrNode> deferredAttrNodes = new ArrayList<DeferredAttrNode>();
 
-        DeferredAttrContext(AttrMode mode, Symbol msym, MethodResolutionPhase phase, InferenceContext inferenceContext) {
+        DeferredAttrContext(AttrMode mode, Symbol msym, MethodResolutionPhase phase,
+                InferenceContext inferenceContext, DeferredAttrContext parent, Warner warn) {
             this.mode = mode;
             this.msym = msym;
             this.phase = phase;
+            this.parent = parent;
+            this.warn = warn;
             this.inferenceContext = inferenceContext;
         }
 
@@ -363,7 +372,7 @@
                 //scan a defensive copy of the node list - this is because a deferred
                 //attribution round can add new nodes to the list
                 for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) {
-                    if (!deferredAttrNode.process()) {
+                    if (!deferredAttrNode.process(this)) {
                         stuckVars.addAll(deferredAttrNode.stuckVars);
                     } else {
                         deferredAttrNodes.remove(deferredAttrNode);
@@ -378,118 +387,120 @@
                 }
             }
         }
+    }
+
+    /**
+     * Class representing a deferred attribution node. It keeps track of
+     * a deferred type, along with the expected target type information.
+     */
+    class DeferredAttrNode implements Infer.FreeTypeListener {
+
+        /** underlying deferred type */
+        DeferredType dt;
+
+        /** underlying target type information */
+        ResultInfo resultInfo;
+
+        /** list of uninferred inference variables causing this node to be stuck */
+        List<Type> stuckVars;
+
+        DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) {
+            this.dt = dt;
+            this.resultInfo = resultInfo;
+            this.stuckVars = stuckVars;
+            if (!stuckVars.isEmpty()) {
+                resultInfo.checkContext.inferenceContext().addFreeTypeListener(stuckVars, this);
+            }
+        }
+
+        @Override
+        public void typesInferred(InferenceContext inferenceContext) {
+            stuckVars = List.nil();
+            resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt));
+        }
 
         /**
-         * Class representing a deferred attribution node. It keeps track of
-         * a deferred type, along with the expected target type information.
+         * Process a deferred attribution node.
+         * Invariant: a stuck node cannot be processed.
          */
-        class DeferredAttrNode implements Infer.FreeTypeListener {
+        @SuppressWarnings("fallthrough")
+        boolean process(DeferredAttrContext deferredAttrContext) {
+            switch (deferredAttrContext.mode) {
+                case SPECULATIVE:
+                    dt.check(resultInfo, List.<Type>nil(), new StructuralStuckChecker());
+                    return true;
+                case CHECK:
+                    if (stuckVars.nonEmpty()) {
+                        return false;
+                    } else {
+                        dt.check(resultInfo, stuckVars, basicCompleter);
+                        return true;
+                    }
+                default:
+                    throw new AssertionError("Bad mode");
+            }
+        }
 
-            /** underlying deferred type */
-            DeferredType dt;
+        /**
+         * Structural checker for stuck expressions
+         */
+        class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter {
 
-            /** underlying target type information */
             ResultInfo resultInfo;
+            InferenceContext inferenceContext;
 
-            /** list of uninferred inference variables causing this node to be stuck */
-            List<Type> stuckVars;
+            public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
+                this.resultInfo = resultInfo;
+                this.inferenceContext = deferredAttrContext.inferenceContext;
+                dt.tree.accept(this);
+                dt.speculativeCache.put(deferredAttrContext.msym, stuckTree, deferredAttrContext.phase);
+                return Type.noType;
+            }
 
-            DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) {
-                this.dt = dt;
-                this.resultInfo = resultInfo;
-                this.stuckVars = stuckVars;
-                if (!stuckVars.isEmpty()) {
-                    resultInfo.checkContext.inferenceContext().addFreeTypeListener(stuckVars, this);
+            @Override
+            public void visitLambda(JCLambda tree) {
+                Check.CheckContext checkContext = resultInfo.checkContext;
+                Type pt = resultInfo.pt;
+                if (inferenceContext.inferencevars.contains(pt)) {
+                    //ok
+                    return;
+                } else {
+                    //must be a functional descriptor
+                    try {
+                        Type desc = types.findDescriptorType(pt);
+                        if (desc.getParameterTypes().length() != tree.params.length()) {
+                            checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda"));
+                        }
+                    } catch (Types.FunctionDescriptorLookupError ex) {
+                        checkContext.report(null, ex.getDiagnostic());
+                    }
                 }
             }
 
             @Override
-            public void typesInferred(InferenceContext inferenceContext) {
-                stuckVars = List.nil();
-                resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt));
+            public void visitNewClass(JCNewClass tree) {
+                //do nothing
             }
 
-            /**
-             * Process a deferred attribution node.
-             * Invariant: a stuck node cannot be processed.
-             */
-            @SuppressWarnings("fallthrough")
-            boolean process() {
-                switch (mode) {
-                    case SPECULATIVE:
-                        dt.check(resultInfo, List.<Type>nil(), new StructuralStuckChecker());
-                        return true;
-                    case CHECK:
-                        if (stuckVars.nonEmpty()) {
-                            return false;
-                        } else {
-                            dt.check(resultInfo, stuckVars, basicCompleter);
-                            return true;
-                        }
-                    default:
-                        throw new AssertionError("Bad mode");
-                }
+            @Override
+            public void visitApply(JCMethodInvocation tree) {
+                //do nothing
             }
 
-            /**
-             * Structural checker for stuck expressions
-             */
-            class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter {
-
-                ResultInfo resultInfo;
-
-                public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
-                    this.resultInfo = resultInfo;
-                    dt.tree.accept(this);
-                    dt.speculativeCache.put(msym, stuckTree, phase);
-                    return Type.noType;
-                }
-
-                @Override
-                public void visitLambda(JCLambda tree) {
-                    Check.CheckContext checkContext = resultInfo.checkContext;
-                    Type pt = resultInfo.pt;
-                    if (inferenceContext.inferencevars.contains(pt)) {
-                        //ok
-                        return;
-                    } else {
-                        //must be a functional descriptor
-                        try {
-                            Type desc = types.findDescriptorType(pt);
-                            if (desc.getParameterTypes().length() != tree.params.length()) {
-                                checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda"));
-                            }
-                        } catch (Types.FunctionDescriptorLookupError ex) {
-                            checkContext.report(null, ex.getDiagnostic());
-                        }
-                    }
-                }
-
-                @Override
-                public void visitNewClass(JCNewClass tree) {
-                    //do nothing
-                }
-
-                @Override
-                public void visitApply(JCMethodInvocation tree) {
-                    //do nothing
-                }
-
-                @Override
-                public void visitReference(JCMemberReference tree) {
-                    Check.CheckContext checkContext = resultInfo.checkContext;
-                    Type pt = resultInfo.pt;
-                    if (inferenceContext.inferencevars.contains(pt)) {
-                        //ok
-                        return;
-                    } else {
-                        try {
-                            //TODO: we should speculative determine if there's a match
-                            //based on arity - if yes, method is applicable.
-                            types.findDescriptorType(pt);
-                        } catch (Types.FunctionDescriptorLookupError ex) {
-                            checkContext.report(null, ex.getDiagnostic());
-                        }
+            @Override
+            public void visitReference(JCMemberReference tree) {
+                Check.CheckContext checkContext = resultInfo.checkContext;
+                Type pt = resultInfo.pt;
+                if (inferenceContext.inferencevars.contains(pt)) {
+                    //ok
+                    return;
+                } else {
+                    try {
+                        //TODO: we should speculative determine if there's a match
+                        //based on arity - if yes, method is applicable.
+                        types.findDescriptorType(pt);
+                    } catch (Types.FunctionDescriptorLookupError ex) {
+                        checkContext.report(null, ex.getDiagnostic());
                     }
                 }
             }
@@ -498,7 +509,7 @@
 
     /** an empty deferred attribution context - all methods throw exceptions */
     final DeferredAttrContext emptyDeferredAttrContext =
-            new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, null) {
+            new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, null, null, null) {
                 @Override
                 void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) {
                     Assert.error("Empty deferred context!");
@@ -521,7 +532,8 @@
 
         protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
             super(String.format("deferredTypeMap[%s]", mode));
-            this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase, infer.emptyContext);
+            this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase,
+                    infer.emptyContext, emptyDeferredAttrContext, types.noWarnings);
         }
 
         protected boolean validState(DeferredType dt) {
--- a/src/share/classes/com/sun/tools/javac/comp/Infer.java	Wed Feb 06 14:03:39 2013 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java	Wed Feb 06 14:04:43 2013 +0000
@@ -269,7 +269,7 @@
         inferenceException.clear();
 
         DeferredAttr.DeferredAttrContext deferredAttrContext =
-                resolveContext.deferredAttrContext(msym, inferenceContext);
+                resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn);
 
         try {
             methodCheck.argumentsAcceptable(env, deferredAttrContext, argtypes, mt.getParameterTypes(), warn);
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Wed Feb 06 14:03:39 2013 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Wed Feb 06 14:04:43 2013 +0000
@@ -564,7 +564,7 @@
                                     methodCheck,
                                     warn);
 
-        methodCheck.argumentsAcceptable(env, currentResolutionContext.deferredAttrContext(m, infer.emptyContext),
+        methodCheck.argumentsAcceptable(env, currentResolutionContext.deferredAttrContext(m, infer.emptyContext, resultInfo, warn),
                                 argtypes, mt.getParameterTypes(), warn);
         return mt;
     }
@@ -3589,8 +3589,8 @@
             candidates = candidates.append(c);
         }
 
-        DeferredAttrContext deferredAttrContext(Symbol sym, InferenceContext inferenceContext) {
-            return deferredAttr.new DeferredAttrContext(attrMode, sym, step, inferenceContext);
+        DeferredAttrContext deferredAttrContext(Symbol sym, InferenceContext inferenceContext, ResultInfo pendingResult, Warner warn) {
+            return deferredAttr.new DeferredAttrContext(attrMode, sym, step, inferenceContext, pendingResult != null ? pendingResult.checkContext.deferredAttrContext() : deferredAttr.emptyDeferredAttrContext, warn);
         }
 
         /**