langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
changeset 24404 cf534ffbc9d8
parent 24400 f05df7f58567
child 24604 7f68545b5128
equal deleted inserted replaced
24403:f2ce14657001 24404:cf534ffbc9d8
    92     Types types;
    92     Types types;
    93     JCDiagnostic.Factory diags;
    93     JCDiagnostic.Factory diags;
    94     public final boolean boxingEnabled;
    94     public final boolean boxingEnabled;
    95     public final boolean varargsEnabled;
    95     public final boolean varargsEnabled;
    96     public final boolean allowMethodHandles;
    96     public final boolean allowMethodHandles;
    97     public final boolean allowStructuralMostSpecific;
    97     public final boolean allowFunctionalInterfaceMostSpecific;
    98     private final boolean debugResolve;
    98     private final boolean debugResolve;
    99     private final boolean compactMethodDiags;
    99     private final boolean compactMethodDiags;
   100     final EnumSet<VerboseResolutionMode> verboseResolutionMode;
   100     final EnumSet<VerboseResolutionMode> verboseResolutionMode;
   101 
   101 
   102     Scope polymorphicSignatureScope;
   102     Scope polymorphicSignatureScope;
   133         compactMethodDiags = options.isSet(Option.XDIAGS, "compact") ||
   133         compactMethodDiags = options.isSet(Option.XDIAGS, "compact") ||
   134                 options.isUnset(Option.XDIAGS) && options.isUnset("rawDiagnostics");
   134                 options.isUnset(Option.XDIAGS) && options.isUnset("rawDiagnostics");
   135         verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
   135         verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
   136         Target target = Target.instance(context);
   136         Target target = Target.instance(context);
   137         allowMethodHandles = target.hasMethodHandles();
   137         allowMethodHandles = target.hasMethodHandles();
   138         allowStructuralMostSpecific = source.allowStructuralMostSpecific();
   138         allowFunctionalInterfaceMostSpecific = source.allowFunctionalInterfaceMostSpecific();
   139         polymorphicSignatureScope = new Scope(syms.noSymbol);
   139         polymorphicSignatureScope = new Scope(syms.noSymbol);
   140 
   140 
   141         inapplicableMethodException = new InapplicableMethodException(diags);
   141         inapplicableMethodException = new InapplicableMethodException(diags);
   142     }
   142     }
   143 
   143 
  1082                 super(strict, deferredAttrContext, rsWarner);
  1082                 super(strict, deferredAttrContext, rsWarner);
  1083                 this.actual = actual;
  1083                 this.actual = actual;
  1084             }
  1084             }
  1085 
  1085 
  1086             public boolean compatible(Type found, Type req, Warner warn) {
  1086             public boolean compatible(Type found, Type req, Warner warn) {
  1087                 if (!allowStructuralMostSpecific || actual == null) {
  1087                 if (allowFunctionalInterfaceMostSpecific &&
  1088                     return super.compatible(found, req, warn);
  1088                         unrelatedFunctionalInterfaces(found, req) &&
  1089                 } else {
  1089                         (actual != null && actual.getTag() == DEFERRED)) {
  1090                     switch (actual.getTag()) {
  1090                     DeferredType dt = (DeferredType) actual;
  1091                         case DEFERRED:
  1091                     DeferredType.SpeculativeCache.Entry e =
  1092                             DeferredType dt = (DeferredType) actual;
  1092                             dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase);
  1093                             DeferredType.SpeculativeCache.Entry e = dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase);
  1093                     if (e != null && e.speculativeTree != deferredAttr.stuckTree) {
  1094                             return (e == null || e.speculativeTree == deferredAttr.stuckTree)
  1094                         return functionalInterfaceMostSpecific(found, req, e.speculativeTree, warn);
  1095                                     ? super.compatible(found, req, warn) :
       
  1096                                       mostSpecific(found, req, e.speculativeTree, warn);
       
  1097                         default:
       
  1098                             return standaloneMostSpecific(found, req, actual, warn);
       
  1099                     }
  1095                     }
  1100                 }
  1096                 }
  1101             }
  1097                 return super.compatible(found, req, warn);
  1102 
  1098             }
  1103             private boolean mostSpecific(Type t, Type s, JCTree tree, Warner warn) {
  1099 
  1104                 MostSpecificChecker msc = new MostSpecificChecker(t, s, warn);
  1100             /** Whether {@code t} and {@code s} are unrelated functional interface types. */
       
  1101             private boolean unrelatedFunctionalInterfaces(Type t, Type s) {
       
  1102                 return types.isFunctionalInterface(t.tsym) &&
       
  1103                        types.isFunctionalInterface(s.tsym) &&
       
  1104                        types.asSuper(t, s.tsym) == null &&
       
  1105                        types.asSuper(s, t.tsym) == null;
       
  1106             }
       
  1107 
       
  1108             /** Parameters {@code t} and {@code s} are unrelated functional interface types. */
       
  1109             private boolean functionalInterfaceMostSpecific(Type t, Type s, JCTree tree, Warner warn) {
       
  1110                 FunctionalInterfaceMostSpecificChecker msc = new FunctionalInterfaceMostSpecificChecker(t, s, warn);
  1105                 msc.scan(tree);
  1111                 msc.scan(tree);
  1106                 return msc.result;
  1112                 return msc.result;
  1107             }
  1113             }
  1108 
  1114 
  1109             boolean polyMostSpecific(Type t1, Type t2, Warner warn) {
       
  1110                 return (!t1.isPrimitive() && t2.isPrimitive())
       
  1111                         ? true : super.compatible(t1, t2, warn);
       
  1112             }
       
  1113 
       
  1114             boolean standaloneMostSpecific(Type t1, Type t2, Type exprType, Warner warn) {
       
  1115                 return (exprType.isPrimitive() == t1.isPrimitive()
       
  1116                         && exprType.isPrimitive() != t2.isPrimitive())
       
  1117                         ? true : super.compatible(t1, t2, warn);
       
  1118             }
       
  1119 
       
  1120             /**
  1115             /**
  1121              * Structural checker for most specific.
  1116              * Tests whether one functional interface type can be considered more specific
       
  1117              * than another unrelated functional interface type for the scanned expression.
  1122              */
  1118              */
  1123             class MostSpecificChecker extends DeferredAttr.PolyScanner {
  1119             class FunctionalInterfaceMostSpecificChecker extends DeferredAttr.PolyScanner {
  1124 
  1120 
  1125                 final Type t;
  1121                 final Type t;
  1126                 final Type s;
  1122                 final Type s;
  1127                 final Warner warn;
  1123                 final Warner warn;
  1128                 boolean result;
  1124                 boolean result;
  1129 
  1125 
  1130                 MostSpecificChecker(Type t, Type s, Warner warn) {
  1126                 /** Parameters {@code t} and {@code s} are unrelated functional interface types. */
       
  1127                 FunctionalInterfaceMostSpecificChecker(Type t, Type s, Warner warn) {
  1131                     this.t = t;
  1128                     this.t = t;
  1132                     this.s = s;
  1129                     this.s = s;
  1133                     this.warn = warn;
  1130                     this.warn = warn;
  1134                     result = true;
  1131                     result = true;
  1135                 }
  1132                 }
  1136 
  1133 
  1137                 @Override
  1134                 @Override
  1138                 void skip(JCTree tree) {
  1135                 void skip(JCTree tree) {
  1139                     result &= standaloneMostSpecific(t, s, tree.type, warn);
  1136                     result &= false;
  1140                 }
  1137                 }
  1141 
  1138 
  1142                 @Override
  1139                 @Override
  1143                 public void visitConditional(JCConditional tree) {
  1140                 public void visitConditional(JCConditional tree) {
  1144                     if (tree.polyKind == PolyKind.STANDALONE) {
  1141                     scan(tree.truepart);
  1145                         result &= standaloneMostSpecific(t, s, tree.type, warn);
  1142                     scan(tree.falsepart);
  1146                     } else {
       
  1147                         super.visitConditional(tree);
       
  1148                     }
       
  1149                 }
       
  1150 
       
  1151                 @Override
       
  1152                 public void visitApply(JCMethodInvocation tree) {
       
  1153                     result &= (tree.polyKind == PolyKind.STANDALONE)
       
  1154                             ? standaloneMostSpecific(t, s, tree.type, warn)
       
  1155                             : polyMostSpecific(t, s, warn);
       
  1156                 }
       
  1157 
       
  1158                 @Override
       
  1159                 public void visitNewClass(JCNewClass tree) {
       
  1160                     result &= (tree.polyKind == PolyKind.STANDALONE)
       
  1161                             ? standaloneMostSpecific(t, s, tree.type, warn)
       
  1162                             : polyMostSpecific(t, s, warn);
       
  1163                 }
  1143                 }
  1164 
  1144 
  1165                 @Override
  1145                 @Override
  1166                 public void visitReference(JCMemberReference tree) {
  1146                 public void visitReference(JCMemberReference tree) {
  1167                     if (types.isFunctionalInterface(t.tsym) &&
  1147                     Type desc_t = types.findDescriptorType(t);
  1168                             types.isFunctionalInterface(s.tsym)) {
  1148                     Type desc_s = types.findDescriptorType(s);
  1169                         Type desc_t = types.findDescriptorType(t);
  1149                     // use inference variables here for more-specific inference (18.5.4)
  1170                         Type desc_s = types.findDescriptorType(s);
  1150                     if (!types.isSameTypes(desc_t.getParameterTypes(),
  1171                         if (types.isSameTypes(desc_t.getParameterTypes(),
  1151                             inferenceContext().asUndetVars(desc_s.getParameterTypes()))) {
  1172                                 inferenceContext().asUndetVars(desc_s.getParameterTypes()))) {
  1152                         result &= false;
  1173                             if (types.asSuper(t, s.tsym) != null ||
  1153                     } else {
  1174                                 types.asSuper(s, t.tsym) != null) {
  1154                         // compare return types
  1175                                 result &= MostSpecificCheckContext.super.compatible(t, s, warn);
  1155                         Type ret_t = desc_t.getReturnType();
  1176                             } else if (!desc_s.getReturnType().hasTag(VOID)) {
  1156                         Type ret_s = desc_s.getReturnType();
  1177                                 //perform structural comparison
  1157                         if (ret_s.hasTag(VOID)) {
  1178                                 Type ret_t = desc_t.getReturnType();
  1158                             result &= true;
  1179                                 Type ret_s = desc_s.getReturnType();
  1159                         } else if (ret_t.hasTag(VOID)) {
  1180                                 result &= ((tree.refPolyKind == PolyKind.STANDALONE)
  1160                             result &= false;
  1181                                         ? standaloneMostSpecific(ret_t, ret_s, tree.sym.type.getReturnType(), warn)
  1161                         } else if (ret_t.isPrimitive() != ret_s.isPrimitive()) {
  1182                                         : polyMostSpecific(ret_t, ret_s, warn));
  1162                             boolean retValIsPrimitive =
  1183                             } else {
  1163                                     tree.refPolyKind == PolyKind.STANDALONE &&
  1184                                 return;
  1164                                     tree.sym.type.getReturnType().isPrimitive();
  1185                             }
  1165                             result &= (retValIsPrimitive == ret_t.isPrimitive()) &&
       
  1166                                       (retValIsPrimitive != ret_s.isPrimitive());
       
  1167                         } else {
       
  1168                             result &= MostSpecificCheckContext.super.compatible(ret_t, ret_s, warn);
  1186                         }
  1169                         }
  1187                     } else {
       
  1188                         result &= false;
       
  1189                     }
  1170                     }
  1190                 }
  1171                 }
  1191 
  1172 
  1192                 @Override
  1173                 @Override
  1193                 public void visitLambda(JCLambda tree) {
  1174                 public void visitLambda(JCLambda tree) {
  1194                     if (types.isFunctionalInterface(t.tsym) &&
  1175                     Type desc_t = types.findDescriptorType(t);
  1195                             types.isFunctionalInterface(s.tsym)) {
  1176                     Type desc_s = types.findDescriptorType(s);
  1196                         Type desc_t = types.findDescriptorType(t);
  1177                     // use inference variables here for more-specific inference (18.5.4)
  1197                         Type desc_s = types.findDescriptorType(s);
  1178                     if (!types.isSameTypes(desc_t.getParameterTypes(),
  1198                         if (types.isSameTypes(desc_t.getParameterTypes(),
  1179                             inferenceContext().asUndetVars(desc_s.getParameterTypes()))) {
  1199                                 inferenceContext().asUndetVars(desc_s.getParameterTypes()))) {
  1180                         result &= false;
  1200                             if (types.asSuper(t, s.tsym) != null ||
  1181                     } else {
  1201                                 types.asSuper(s, t.tsym) != null) {
  1182                         // compare return types
  1202                                 result &= MostSpecificCheckContext.super.compatible(t, s, warn);
  1183                         Type ret_t = desc_t.getReturnType();
  1203                             } else if (!desc_s.getReturnType().hasTag(VOID)) {
  1184                         Type ret_s = desc_s.getReturnType();
  1204                                 //perform structural comparison
  1185                         if (ret_s.hasTag(VOID)) {
  1205                                 Type ret_t = desc_t.getReturnType();
  1186                             result &= true;
  1206                                 Type ret_s = desc_s.getReturnType();
  1187                         } else if (ret_t.hasTag(VOID)) {
  1207                                 scanLambdaBody(tree, ret_t, ret_s);
  1188                             result &= false;
  1208                             } else {
  1189                         } else if (unrelatedFunctionalInterfaces(ret_t, ret_s)) {
  1209                                 return;
  1190                             for (JCExpression expr : lambdaResults(tree)) {
       
  1191                                 result &= functionalInterfaceMostSpecific(ret_t, ret_s, expr, warn);
  1210                             }
  1192                             }
       
  1193                         } else if (ret_t.isPrimitive() != ret_s.isPrimitive()) {
       
  1194                             for (JCExpression expr : lambdaResults(tree)) {
       
  1195                                 boolean retValIsPrimitive = expr.isStandalone() && expr.type.isPrimitive();
       
  1196                                 result &= (retValIsPrimitive == ret_t.isPrimitive()) &&
       
  1197                                           (retValIsPrimitive != ret_s.isPrimitive());
       
  1198                             }
       
  1199                         } else {
       
  1200                             result &= MostSpecificCheckContext.super.compatible(ret_t, ret_s, warn);
  1211                         }
  1201                         }
       
  1202                     }
       
  1203                 }
       
  1204                 //where
       
  1205 
       
  1206                 private List<JCExpression> lambdaResults(JCLambda lambda) {
       
  1207                     if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
       
  1208                         return List.of((JCExpression) lambda.body);
  1212                     } else {
  1209                     } else {
  1213                         result &= false;
  1210                         final ListBuffer<JCExpression> buffer = new ListBuffer<>();
  1214                     }
       
  1215                 }
       
  1216                 //where
       
  1217 
       
  1218                 void scanLambdaBody(JCLambda lambda, final Type t, final Type s) {
       
  1219                     if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
       
  1220                         result &= MostSpecificCheckContext.this.mostSpecific(t, s, lambda.body, warn);
       
  1221                     } else {
       
  1222                         DeferredAttr.LambdaReturnScanner lambdaScanner =
  1211                         DeferredAttr.LambdaReturnScanner lambdaScanner =
  1223                                 new DeferredAttr.LambdaReturnScanner() {
  1212                                 new DeferredAttr.LambdaReturnScanner() {
  1224                                     @Override
  1213                                     @Override
  1225                                     public void visitReturn(JCReturn tree) {
  1214                                     public void visitReturn(JCReturn tree) {
  1226                                         if (tree.expr != null) {
  1215                                         if (tree.expr != null) {
  1227                                             result &= MostSpecificCheckContext.this.mostSpecific(t, s, tree.expr, warn);
  1216                                             buffer.append(tree.expr);
  1228                                         }
  1217                                         }
  1229                                     }
  1218                                     }
  1230                                 };
  1219                                 };
  1231                         lambdaScanner.scan(lambda.body);
  1220                         lambdaScanner.scan(lambda.body);
       
  1221                         return buffer.toList();
  1232                     }
  1222                     }
  1233                 }
  1223                 }
  1234             }
  1224             }
       
  1225 
  1235         }
  1226         }
  1236 
  1227 
  1237         public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
  1228         public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
  1238             Assert.error("Cannot get here!");
  1229             Assert.error("Cannot get here!");
  1239             return null;
  1230             return null;