< prev index next >

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

Print this page

 817          * Structural checker for stuck expressions
 818          */
 819         class StructuralStuckChecker extends TreeScanner {
 820 
 821             ResultInfo resultInfo;
 822             InferenceContext inferenceContext;
 823             Env<AttrContext> env;
 824 
 825             public void check(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
 826                 this.resultInfo = resultInfo;
 827                 this.inferenceContext = deferredAttrContext.inferenceContext;
 828                 this.env = dt.env;
 829                 dt.tree.accept(this);
 830                 dt.speculativeCache.put(stuckTree, resultInfo);
 831             }
 832 
 833             @Override
 834             public void visitLambda(JCLambda tree) {
 835                 Check.CheckContext checkContext = resultInfo.checkContext;
 836                 Type pt = resultInfo.pt;
 837                 if (!inferenceContext.inferencevars.contains(pt)) {
 838                     //must be a functional descriptor
 839                     Type descriptorType = null;
 840                     try {
 841                         descriptorType = types.findDescriptorType(pt);
 842                     } catch (Types.FunctionDescriptorLookupError ex) {
 843                         checkContext.report(null, ex.getDiagnostic());
 844                     }
 845 
 846                     if (descriptorType.getParameterTypes().length() != tree.params.length()) {
 847                         checkContext.report(tree,
 848                                 diags.fragment(Fragments.IncompatibleArgTypesInLambda));
 849                     }
 850 
 851                     Type currentReturnType = descriptorType.getReturnType();
 852                     boolean returnTypeIsVoid = currentReturnType.hasTag(VOID);
 853                     if (tree.getBodyKind() == BodyKind.EXPRESSION) {
 854                         boolean isExpressionCompatible = !returnTypeIsVoid ||
 855                             TreeInfo.isExpressionStatement((JCExpression)tree.getBody());
 856                         if (!isExpressionCompatible) {
 857                             resultInfo.checkContext.report(tree.pos(),

1101                 }
1102             });
1103             return super.visit(dt);
1104         }
1105 
1106         private List<Type> map(List<Type> ts, List<Type> pts) {
1107             if (ts.nonEmpty()) {
1108                 List<Type> tail1 = map(ts.tail, pts != null ? pts.tail : null);
1109                 Type t = visit(ts.head, pts != null && pts.nonEmpty() ? pts.head : null);
1110                 if (tail1 != ts.tail || t != ts.head)
1111                     return tail1.prepend(t);
1112             }
1113             return ts;
1114         }
1115     }
1116 
1117     /**
1118      * A special tree scanner that would only visit portions of a given tree.
1119      * The set of nodes visited by the scanner can be customized at construction-time.
1120      */
1121     abstract static class FilterScanner extends com.sun.tools.javac.tree.TreeScanner {
1122 
1123         final Predicate<JCTree> treeFilter;
1124 
1125         FilterScanner(final Set<JCTree.Tag> validTags) {
1126             this.treeFilter = t -> validTags.contains(t.getTag());
1127         }
1128 
1129         @Override
1130         public void scan(JCTree tree) {
1131             if (tree != null) {
1132                 if (treeFilter.test(tree)) {
1133                     super.scan(tree);
1134                 } else {
1135                     skip(tree);
1136                 }
1137             }
1138         }
1139 
1140         /**
1141          * handler that is executed when a node has been discarded
1142          */
1143         void skip(JCTree tree) {}
1144     }
1145 
1146     /**
1147      * A tree scanner suitable for visiting the target-type dependent nodes of
1148      * a given argument expression.
1149      */
1150     static class PolyScanner extends FilterScanner {
1151 
1152         PolyScanner() {
1153             super(EnumSet.of(CONDEXPR, PARENS, LAMBDA, REFERENCE, SWITCH_EXPRESSION));
1154         }
1155     }
1156 
1157     /**
1158      * A tree scanner suitable for visiting the target-type dependent nodes nested
1159      * within a lambda expression body.
1160      */
1161     static class LambdaReturnScanner extends FilterScanner {
1162 
1163         LambdaReturnScanner() {

1209         public CheckStuckPolicy(ResultInfo resultInfo, DeferredType dt) {
1210             this.pt = resultInfo.pt;
1211             this.inferenceContext = resultInfo.checkContext.inferenceContext();
1212             scan(dt.tree);
1213             if (!stuckVars.isEmpty()) {
1214                 resultInfo.checkContext.inferenceContext()
1215                         .addFreeTypeListener(List.from(stuckVars), this);
1216             }
1217         }
1218 
1219         @Override
1220         public void typesInferred(InferenceContext inferenceContext) {
1221             stuckVars.clear();
1222         }
1223 
1224         @Override
1225         public void visitLambda(JCLambda tree) {
1226             if (inferenceContext.inferenceVars().contains(pt)) {
1227                 stuckVars.add(pt);
1228             }
1229             if (!types.isFunctionalInterface(pt)) {
1230                 return;
1231             }
1232             Type descType = types.findDescriptorType(pt);
1233             List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
1234             if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT &&
1235                     freeArgVars.nonEmpty()) {
1236                 stuckVars.addAll(freeArgVars);
1237                 depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType()));
1238                 depVars.addAll(inferenceContext.freeVarsIn(descType.getThrownTypes()));
1239             }
1240             scanLambdaBody(tree, descType.getReturnType());
1241         }
1242 
1243         @Override
1244         public void visitReference(JCMemberReference tree) {
1245             scan(tree.expr);
1246             if (inferenceContext.inferenceVars().contains(pt)) {
1247                 stuckVars.add(pt);
1248                 return;
1249             }

 817          * Structural checker for stuck expressions
 818          */
 819         class StructuralStuckChecker extends TreeScanner {
 820 
 821             ResultInfo resultInfo;
 822             InferenceContext inferenceContext;
 823             Env<AttrContext> env;
 824 
 825             public void check(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
 826                 this.resultInfo = resultInfo;
 827                 this.inferenceContext = deferredAttrContext.inferenceContext;
 828                 this.env = dt.env;
 829                 dt.tree.accept(this);
 830                 dt.speculativeCache.put(stuckTree, resultInfo);
 831             }
 832 
 833             @Override
 834             public void visitLambda(JCLambda tree) {
 835                 Check.CheckContext checkContext = resultInfo.checkContext;
 836                 Type pt = resultInfo.pt;
 837                 if (!types.isQuoted(pt) && !inferenceContext.inferencevars.contains(pt)) {
 838                     //must be a functional descriptor
 839                     Type descriptorType = null;
 840                     try {
 841                         descriptorType = types.findDescriptorType(pt);
 842                     } catch (Types.FunctionDescriptorLookupError ex) {
 843                         checkContext.report(null, ex.getDiagnostic());
 844                     }
 845 
 846                     if (descriptorType.getParameterTypes().length() != tree.params.length()) {
 847                         checkContext.report(tree,
 848                                 diags.fragment(Fragments.IncompatibleArgTypesInLambda));
 849                     }
 850 
 851                     Type currentReturnType = descriptorType.getReturnType();
 852                     boolean returnTypeIsVoid = currentReturnType.hasTag(VOID);
 853                     if (tree.getBodyKind() == BodyKind.EXPRESSION) {
 854                         boolean isExpressionCompatible = !returnTypeIsVoid ||
 855                             TreeInfo.isExpressionStatement((JCExpression)tree.getBody());
 856                         if (!isExpressionCompatible) {
 857                             resultInfo.checkContext.report(tree.pos(),

1101                 }
1102             });
1103             return super.visit(dt);
1104         }
1105 
1106         private List<Type> map(List<Type> ts, List<Type> pts) {
1107             if (ts.nonEmpty()) {
1108                 List<Type> tail1 = map(ts.tail, pts != null ? pts.tail : null);
1109                 Type t = visit(ts.head, pts != null && pts.nonEmpty() ? pts.head : null);
1110                 if (tail1 != ts.tail || t != ts.head)
1111                     return tail1.prepend(t);
1112             }
1113             return ts;
1114         }
1115     }
1116 
1117     /**
1118      * A special tree scanner that would only visit portions of a given tree.
1119      * The set of nodes visited by the scanner can be customized at construction-time.
1120      */
1121     public abstract static class FilterScanner extends com.sun.tools.javac.tree.TreeScanner {
1122 
1123         final Predicate<JCTree> treeFilter;
1124 
1125         protected FilterScanner(final Set<JCTree.Tag> validTags) {
1126             this.treeFilter = t -> validTags.contains(t.getTag());
1127         }
1128 
1129         @Override
1130         public void scan(JCTree tree) {
1131             if (tree != null) {
1132                 if (treeFilter.test(tree)) {
1133                     super.scan(tree);
1134                 } else {
1135                     skip(tree);
1136                 }
1137             }
1138         }
1139 
1140         /**
1141          * handler that is executed when a node has been discarded
1142          */
1143         protected void skip(JCTree tree) {}
1144     }
1145 
1146     /**
1147      * A tree scanner suitable for visiting the target-type dependent nodes of
1148      * a given argument expression.
1149      */
1150     static class PolyScanner extends FilterScanner {
1151 
1152         PolyScanner() {
1153             super(EnumSet.of(CONDEXPR, PARENS, LAMBDA, REFERENCE, SWITCH_EXPRESSION));
1154         }
1155     }
1156 
1157     /**
1158      * A tree scanner suitable for visiting the target-type dependent nodes nested
1159      * within a lambda expression body.
1160      */
1161     static class LambdaReturnScanner extends FilterScanner {
1162 
1163         LambdaReturnScanner() {

1209         public CheckStuckPolicy(ResultInfo resultInfo, DeferredType dt) {
1210             this.pt = resultInfo.pt;
1211             this.inferenceContext = resultInfo.checkContext.inferenceContext();
1212             scan(dt.tree);
1213             if (!stuckVars.isEmpty()) {
1214                 resultInfo.checkContext.inferenceContext()
1215                         .addFreeTypeListener(List.from(stuckVars), this);
1216             }
1217         }
1218 
1219         @Override
1220         public void typesInferred(InferenceContext inferenceContext) {
1221             stuckVars.clear();
1222         }
1223 
1224         @Override
1225         public void visitLambda(JCLambda tree) {
1226             if (inferenceContext.inferenceVars().contains(pt)) {
1227                 stuckVars.add(pt);
1228             }
1229             if (types.isQuoted(pt) || !types.isFunctionalInterface(pt)) {
1230                 return;
1231             }
1232             Type descType = types.findDescriptorType(pt);
1233             List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
1234             if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT &&
1235                     freeArgVars.nonEmpty()) {
1236                 stuckVars.addAll(freeArgVars);
1237                 depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType()));
1238                 depVars.addAll(inferenceContext.freeVarsIn(descType.getThrownTypes()));
1239             }
1240             scanLambdaBody(tree, descType.getReturnType());
1241         }
1242 
1243         @Override
1244         public void visitReference(JCMemberReference tree) {
1245             scan(tree.expr);
1246             if (inferenceContext.inferenceVars().contains(pt)) {
1247                 stuckVars.add(pt);
1248                 return;
1249             }
< prev index next >