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

changeset 1571
af8417e590f4
parent 1562
2154ed9ff6c8
child 1581
4ff468de829d
     1.1 --- a/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Mon Feb 04 18:08:53 2013 -0500
     1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java	Sun Feb 17 16:44:55 2013 -0500
     1.3 @@ -234,7 +234,7 @@
     1.4                      dt.speculativeCache.put(deferredAttrContext.msym, speculativeTree, deferredAttrContext.phase);
     1.5                      return speculativeTree.type;
     1.6                  case CHECK:
     1.7 -                    Assert.check(dt.mode == AttrMode.SPECULATIVE);
     1.8 +                    Assert.check(dt.mode != null);
     1.9                      return attr.attribTree(dt.tree, dt.env, resultInfo);
    1.10              }
    1.11              Assert.error();
    1.12 @@ -242,6 +242,13 @@
    1.13          }
    1.14      };
    1.15  
    1.16 +    DeferredTypeCompleter dummyCompleter = new DeferredTypeCompleter() {
    1.17 +        public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
    1.18 +            Assert.check(deferredAttrContext.mode == AttrMode.CHECK);
    1.19 +            return dt.tree.type = Type.noType;
    1.20 +        }
    1.21 +    };
    1.22 +
    1.23      /**
    1.24       * The 'mode' in which the deferred type is to be type-checked
    1.25       */
    1.26 @@ -332,13 +339,22 @@
    1.27          /** inference context */
    1.28          final InferenceContext inferenceContext;
    1.29  
    1.30 +        /** parent deferred context */
    1.31 +        final DeferredAttrContext parent;
    1.32 +
    1.33 +        /** Warner object to report warnings */
    1.34 +        final Warner warn;
    1.35 +
    1.36          /** list of deferred attribution nodes to be processed */
    1.37          ArrayList<DeferredAttrNode> deferredAttrNodes = new ArrayList<DeferredAttrNode>();
    1.38  
    1.39 -        DeferredAttrContext(AttrMode mode, Symbol msym, MethodResolutionPhase phase, InferenceContext inferenceContext) {
    1.40 +        DeferredAttrContext(AttrMode mode, Symbol msym, MethodResolutionPhase phase,
    1.41 +                InferenceContext inferenceContext, DeferredAttrContext parent, Warner warn) {
    1.42              this.mode = mode;
    1.43              this.msym = msym;
    1.44              this.phase = phase;
    1.45 +            this.parent = parent;
    1.46 +            this.warn = warn;
    1.47              this.inferenceContext = inferenceContext;
    1.48          }
    1.49  
    1.50 @@ -363,7 +379,7 @@
    1.51                  //scan a defensive copy of the node list - this is because a deferred
    1.52                  //attribution round can add new nodes to the list
    1.53                  for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) {
    1.54 -                    if (!deferredAttrNode.process()) {
    1.55 +                    if (!deferredAttrNode.process(this)) {
    1.56                          stuckVars.addAll(deferredAttrNode.stuckVars);
    1.57                      } else {
    1.58                          deferredAttrNodes.remove(deferredAttrNode);
    1.59 @@ -373,123 +389,133 @@
    1.60                  if (!progress) {
    1.61                      //remove all variables that have already been instantiated
    1.62                      //from the list of stuck variables
    1.63 -                    inferenceContext.solveAny(inferenceContext.freeVarsIn(List.from(stuckVars)), types, infer);
    1.64 -                    inferenceContext.notifyChange(types);
    1.65 +                    inferenceContext.solveAny(List.from(stuckVars), warn);
    1.66 +                    inferenceContext.notifyChange();
    1.67                  }
    1.68              }
    1.69          }
    1.70 +    }
    1.71 +
    1.72 +    /**
    1.73 +     * Class representing a deferred attribution node. It keeps track of
    1.74 +     * a deferred type, along with the expected target type information.
    1.75 +     */
    1.76 +    class DeferredAttrNode implements Infer.FreeTypeListener {
    1.77 +
    1.78 +        /** underlying deferred type */
    1.79 +        DeferredType dt;
    1.80 +
    1.81 +        /** underlying target type information */
    1.82 +        ResultInfo resultInfo;
    1.83 +
    1.84 +        /** list of uninferred inference variables causing this node to be stuck */
    1.85 +        List<Type> stuckVars;
    1.86 +
    1.87 +        DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) {
    1.88 +            this.dt = dt;
    1.89 +            this.resultInfo = resultInfo;
    1.90 +            this.stuckVars = stuckVars;
    1.91 +            if (!stuckVars.isEmpty()) {
    1.92 +                resultInfo.checkContext.inferenceContext().addFreeTypeListener(stuckVars, this);
    1.93 +            }
    1.94 +        }
    1.95 +
    1.96 +        @Override
    1.97 +        public void typesInferred(InferenceContext inferenceContext) {
    1.98 +            stuckVars = List.nil();
    1.99 +            resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt));
   1.100 +        }
   1.101 +
   1.102 +        /**
   1.103 +         * Process a deferred attribution node.
   1.104 +         * Invariant: a stuck node cannot be processed.
   1.105 +         */
   1.106 +        @SuppressWarnings("fallthrough")
   1.107 +        boolean process(DeferredAttrContext deferredAttrContext) {
   1.108 +            switch (deferredAttrContext.mode) {
   1.109 +                case SPECULATIVE:
   1.110 +                    dt.check(resultInfo, List.<Type>nil(), new StructuralStuckChecker());
   1.111 +                    return true;
   1.112 +                case CHECK:
   1.113 +                    if (stuckVars.nonEmpty()) {
   1.114 +                        //stuck expression - see if we can propagate
   1.115 +                        if (deferredAttrContext.parent != emptyDeferredAttrContext &&
   1.116 +                                Type.containsAny(deferredAttrContext.parent.inferenceContext.inferencevars, List.from(stuckVars))) {
   1.117 +                            deferredAttrContext.parent.deferredAttrNodes.add(this);
   1.118 +                            dt.check(resultInfo, List.<Type>nil(), dummyCompleter);
   1.119 +                            return true;
   1.120 +                        } else {
   1.121 +                            return false;
   1.122 +                        }
   1.123 +                    } else {
   1.124 +                        dt.check(resultInfo, stuckVars, basicCompleter);
   1.125 +                        return true;
   1.126 +                    }
   1.127 +                default:
   1.128 +                    throw new AssertionError("Bad mode");
   1.129 +            }
   1.130 +        }
   1.131  
   1.132          /**
   1.133 -         * Class representing a deferred attribution node. It keeps track of
   1.134 -         * a deferred type, along with the expected target type information.
   1.135 +         * Structural checker for stuck expressions
   1.136           */
   1.137 -        class DeferredAttrNode implements Infer.InferenceContext.FreeTypeListener {
   1.138 +        class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter {
   1.139  
   1.140 -            /** underlying deferred type */
   1.141 -            DeferredType dt;
   1.142 +            ResultInfo resultInfo;
   1.143 +            InferenceContext inferenceContext;
   1.144  
   1.145 -            /** underlying target type information */
   1.146 -            ResultInfo resultInfo;
   1.147 +            public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
   1.148 +                this.resultInfo = resultInfo;
   1.149 +                this.inferenceContext = deferredAttrContext.inferenceContext;
   1.150 +                dt.tree.accept(this);
   1.151 +                dt.speculativeCache.put(deferredAttrContext.msym, stuckTree, deferredAttrContext.phase);
   1.152 +                return Type.noType;
   1.153 +            }
   1.154  
   1.155 -            /** list of uninferred inference variables causing this node to be stuck */
   1.156 -            List<Type> stuckVars;
   1.157 -
   1.158 -            DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) {
   1.159 -                this.dt = dt;
   1.160 -                this.resultInfo = resultInfo;
   1.161 -                this.stuckVars = stuckVars;
   1.162 -                if (!stuckVars.isEmpty()) {
   1.163 -                    resultInfo.checkContext.inferenceContext().addFreeTypeListener(stuckVars, this);
   1.164 +            @Override
   1.165 +            public void visitLambda(JCLambda tree) {
   1.166 +                Check.CheckContext checkContext = resultInfo.checkContext;
   1.167 +                Type pt = resultInfo.pt;
   1.168 +                if (inferenceContext.inferencevars.contains(pt)) {
   1.169 +                    //ok
   1.170 +                    return;
   1.171 +                } else {
   1.172 +                    //must be a functional descriptor
   1.173 +                    try {
   1.174 +                        Type desc = types.findDescriptorType(pt);
   1.175 +                        if (desc.getParameterTypes().length() != tree.params.length()) {
   1.176 +                            checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda"));
   1.177 +                        }
   1.178 +                    } catch (Types.FunctionDescriptorLookupError ex) {
   1.179 +                        checkContext.report(null, ex.getDiagnostic());
   1.180 +                    }
   1.181                  }
   1.182              }
   1.183  
   1.184              @Override
   1.185 -            public void typesInferred(InferenceContext inferenceContext) {
   1.186 -                stuckVars = List.nil();
   1.187 -                resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt, types));
   1.188 +            public void visitNewClass(JCNewClass tree) {
   1.189 +                //do nothing
   1.190              }
   1.191  
   1.192 -            /**
   1.193 -             * Process a deferred attribution node.
   1.194 -             * Invariant: a stuck node cannot be processed.
   1.195 -             */
   1.196 -            @SuppressWarnings("fallthrough")
   1.197 -            boolean process() {
   1.198 -                switch (mode) {
   1.199 -                    case SPECULATIVE:
   1.200 -                        dt.check(resultInfo, List.<Type>nil(), new StructuralStuckChecker());
   1.201 -                        return true;
   1.202 -                    case CHECK:
   1.203 -                        if (stuckVars.nonEmpty()) {
   1.204 -                            return false;
   1.205 -                        } else {
   1.206 -                            dt.check(resultInfo, stuckVars, basicCompleter);
   1.207 -                            return true;
   1.208 -                        }
   1.209 -                    default:
   1.210 -                        throw new AssertionError("Bad mode");
   1.211 -                }
   1.212 +            @Override
   1.213 +            public void visitApply(JCMethodInvocation tree) {
   1.214 +                //do nothing
   1.215              }
   1.216  
   1.217 -            /**
   1.218 -             * Structural checker for stuck expressions
   1.219 -             */
   1.220 -            class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter {
   1.221 -
   1.222 -                ResultInfo resultInfo;
   1.223 -
   1.224 -                public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
   1.225 -                    this.resultInfo = resultInfo;
   1.226 -                    dt.tree.accept(this);
   1.227 -                    dt.speculativeCache.put(msym, stuckTree, phase);
   1.228 -                    return Type.noType;
   1.229 -                }
   1.230 -
   1.231 -                @Override
   1.232 -                public void visitLambda(JCLambda tree) {
   1.233 -                    Check.CheckContext checkContext = resultInfo.checkContext;
   1.234 -                    Type pt = resultInfo.pt;
   1.235 -                    if (inferenceContext.inferencevars.contains(pt)) {
   1.236 -                        //ok
   1.237 -                        return;
   1.238 -                    } else {
   1.239 -                        //must be a functional descriptor
   1.240 -                        try {
   1.241 -                            Type desc = types.findDescriptorType(pt);
   1.242 -                            if (desc.getParameterTypes().length() != tree.params.length()) {
   1.243 -                                checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda"));
   1.244 -                            }
   1.245 -                        } catch (Types.FunctionDescriptorLookupError ex) {
   1.246 -                            checkContext.report(null, ex.getDiagnostic());
   1.247 -                        }
   1.248 -                    }
   1.249 -                }
   1.250 -
   1.251 -                @Override
   1.252 -                public void visitNewClass(JCNewClass tree) {
   1.253 -                    //do nothing
   1.254 -                }
   1.255 -
   1.256 -                @Override
   1.257 -                public void visitApply(JCMethodInvocation tree) {
   1.258 -                    //do nothing
   1.259 -                }
   1.260 -
   1.261 -                @Override
   1.262 -                public void visitReference(JCMemberReference tree) {
   1.263 -                    Check.CheckContext checkContext = resultInfo.checkContext;
   1.264 -                    Type pt = resultInfo.pt;
   1.265 -                    if (inferenceContext.inferencevars.contains(pt)) {
   1.266 -                        //ok
   1.267 -                        return;
   1.268 -                    } else {
   1.269 -                        try {
   1.270 -                            //TODO: we should speculative determine if there's a match
   1.271 -                            //based on arity - if yes, method is applicable.
   1.272 -                            types.findDescriptorType(pt);
   1.273 -                        } catch (Types.FunctionDescriptorLookupError ex) {
   1.274 -                            checkContext.report(null, ex.getDiagnostic());
   1.275 -                        }
   1.276 +            @Override
   1.277 +            public void visitReference(JCMemberReference tree) {
   1.278 +                Check.CheckContext checkContext = resultInfo.checkContext;
   1.279 +                Type pt = resultInfo.pt;
   1.280 +                if (inferenceContext.inferencevars.contains(pt)) {
   1.281 +                    //ok
   1.282 +                    return;
   1.283 +                } else {
   1.284 +                    try {
   1.285 +                        //TODO: we should speculative determine if there's a match
   1.286 +                        //based on arity - if yes, method is applicable.
   1.287 +                        types.findDescriptorType(pt);
   1.288 +                    } catch (Types.FunctionDescriptorLookupError ex) {
   1.289 +                        checkContext.report(null, ex.getDiagnostic());
   1.290                      }
   1.291                  }
   1.292              }
   1.293 @@ -498,7 +524,7 @@
   1.294  
   1.295      /** an empty deferred attribution context - all methods throw exceptions */
   1.296      final DeferredAttrContext emptyDeferredAttrContext =
   1.297 -            new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, null) {
   1.298 +            new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, null, null, null) {
   1.299                  @Override
   1.300                  void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) {
   1.301                      Assert.error("Empty deferred context!");
   1.302 @@ -521,7 +547,8 @@
   1.303  
   1.304          protected DeferredTypeMap(AttrMode mode, Symbol msym, MethodResolutionPhase phase) {
   1.305              super(String.format("deferredTypeMap[%s]", mode));
   1.306 -            this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase, infer.emptyContext);
   1.307 +            this.deferredAttrContext = new DeferredAttrContext(mode, msym, phase,
   1.308 +                    infer.emptyContext, emptyDeferredAttrContext, types.noWarnings);
   1.309          }
   1.310  
   1.311          protected boolean validState(DeferredType dt) {

mercurial