1079 super(strict, deferredAttrContext, rsWarner); |
1079 super(strict, deferredAttrContext, rsWarner); |
1080 this.actual = actual; |
1080 this.actual = actual; |
1081 } |
1081 } |
1082 |
1082 |
1083 public boolean compatible(Type found, Type req, Warner warn) { |
1083 public boolean compatible(Type found, Type req, Warner warn) { |
1084 if (!allowStructuralMostSpecific || actual == null) { |
1084 if (allowFunctionalInterfaceMostSpecific && |
1085 return super.compatible(found, req, warn); |
1085 unrelatedFunctionalInterfaces(found, req) && |
1086 } else { |
1086 (actual != null && actual.getTag() == DEFERRED)) { |
1087 switch (actual.getTag()) { |
1087 DeferredType dt = (DeferredType) actual; |
1088 case DEFERRED: |
1088 DeferredType.SpeculativeCache.Entry e = |
1089 DeferredType dt = (DeferredType) actual; |
1089 dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase); |
1090 DeferredType.SpeculativeCache.Entry e = dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase); |
1090 if (e != null && e.speculativeTree != deferredAttr.stuckTree) { |
1091 return (e == null || e.speculativeTree == deferredAttr.stuckTree) |
1091 return functionalInterfaceMostSpecific(found, req, e.speculativeTree, warn); |
1092 ? super.compatible(found, req, warn) : |
|
1093 mostSpecific(found, req, e.speculativeTree, warn); |
|
1094 default: |
|
1095 return standaloneMostSpecific(found, req, actual, warn); |
|
1096 } |
1092 } |
1097 } |
1093 } |
1098 } |
1094 return super.compatible(found, req, warn); |
1099 |
1095 } |
1100 private boolean mostSpecific(Type t, Type s, JCTree tree, Warner warn) { |
1096 |
1101 MostSpecificChecker msc = new MostSpecificChecker(t, s, warn); |
1097 /** Whether {@code t} and {@code s} are unrelated functional interface types. */ |
|
1098 private boolean unrelatedFunctionalInterfaces(Type t, Type s) { |
|
1099 return types.isFunctionalInterface(t.tsym) && |
|
1100 types.isFunctionalInterface(s.tsym) && |
|
1101 types.asSuper(t, s.tsym) == null && |
|
1102 types.asSuper(s, t.tsym) == null; |
|
1103 } |
|
1104 |
|
1105 /** Parameters {@code t} and {@code s} are unrelated functional interface types. */ |
|
1106 private boolean functionalInterfaceMostSpecific(Type t, Type s, JCTree tree, Warner warn) { |
|
1107 FunctionalInterfaceMostSpecificChecker msc = new FunctionalInterfaceMostSpecificChecker(t, s, warn); |
1102 msc.scan(tree); |
1108 msc.scan(tree); |
1103 return msc.result; |
1109 return msc.result; |
1104 } |
1110 } |
1105 |
1111 |
1106 boolean polyMostSpecific(Type t1, Type t2, Warner warn) { |
|
1107 return (!t1.isPrimitive() && t2.isPrimitive()) |
|
1108 ? true : super.compatible(t1, t2, warn); |
|
1109 } |
|
1110 |
|
1111 boolean standaloneMostSpecific(Type t1, Type t2, Type exprType, Warner warn) { |
|
1112 return (exprType.isPrimitive() == t1.isPrimitive() |
|
1113 && exprType.isPrimitive() != t2.isPrimitive()) |
|
1114 ? true : super.compatible(t1, t2, warn); |
|
1115 } |
|
1116 |
|
1117 /** |
1112 /** |
1118 * Structural checker for most specific. |
1113 * Tests whether one functional interface type can be considered more specific |
|
1114 * than another unrelated functional interface type for the scanned expression. |
1119 */ |
1115 */ |
1120 class MostSpecificChecker extends DeferredAttr.PolyScanner { |
1116 class FunctionalInterfaceMostSpecificChecker extends DeferredAttr.PolyScanner { |
1121 |
1117 |
1122 final Type t; |
1118 final Type t; |
1123 final Type s; |
1119 final Type s; |
1124 final Warner warn; |
1120 final Warner warn; |
1125 boolean result; |
1121 boolean result; |
1126 |
1122 |
1127 MostSpecificChecker(Type t, Type s, Warner warn) { |
1123 /** Parameters {@code t} and {@code s} are unrelated functional interface types. */ |
|
1124 FunctionalInterfaceMostSpecificChecker(Type t, Type s, Warner warn) { |
1128 this.t = t; |
1125 this.t = t; |
1129 this.s = s; |
1126 this.s = s; |
1130 this.warn = warn; |
1127 this.warn = warn; |
1131 result = true; |
1128 result = true; |
1132 } |
1129 } |
1133 |
1130 |
1134 @Override |
1131 @Override |
1135 void skip(JCTree tree) { |
1132 void skip(JCTree tree) { |
1136 result &= standaloneMostSpecific(t, s, tree.type, warn); |
1133 result &= false; |
1137 } |
1134 } |
1138 |
1135 |
1139 @Override |
1136 @Override |
1140 public void visitConditional(JCConditional tree) { |
1137 public void visitConditional(JCConditional tree) { |
1141 if (tree.polyKind == PolyKind.STANDALONE) { |
1138 scan(tree.truepart); |
1142 result &= standaloneMostSpecific(t, s, tree.type, warn); |
1139 scan(tree.falsepart); |
1143 } else { |
|
1144 super.visitConditional(tree); |
|
1145 } |
|
1146 } |
|
1147 |
|
1148 @Override |
|
1149 public void visitApply(JCMethodInvocation tree) { |
|
1150 result &= (tree.polyKind == PolyKind.STANDALONE) |
|
1151 ? standaloneMostSpecific(t, s, tree.type, warn) |
|
1152 : polyMostSpecific(t, s, warn); |
|
1153 } |
|
1154 |
|
1155 @Override |
|
1156 public void visitNewClass(JCNewClass tree) { |
|
1157 result &= (tree.polyKind == PolyKind.STANDALONE) |
|
1158 ? standaloneMostSpecific(t, s, tree.type, warn) |
|
1159 : polyMostSpecific(t, s, warn); |
|
1160 } |
1140 } |
1161 |
1141 |
1162 @Override |
1142 @Override |
1163 public void visitReference(JCMemberReference tree) { |
1143 public void visitReference(JCMemberReference tree) { |
1164 if (types.isFunctionalInterface(t.tsym) && |
1144 Type desc_t = types.findDescriptorType(t); |
1165 types.isFunctionalInterface(s.tsym)) { |
1145 Type desc_s = types.findDescriptorType(s); |
1166 Type desc_t = types.findDescriptorType(t); |
1146 // use inference variables here for more-specific inference (18.5.4) |
1167 Type desc_s = types.findDescriptorType(s); |
1147 if (!types.isSameTypes(desc_t.getParameterTypes(), |
1168 if (types.isSameTypes(desc_t.getParameterTypes(), |
1148 inferenceContext().asUndetVars(desc_s.getParameterTypes()))) { |
1169 inferenceContext().asUndetVars(desc_s.getParameterTypes()))) { |
1149 result &= false; |
1170 if (types.asSuper(t, s.tsym) != null || |
1150 } else { |
1171 types.asSuper(s, t.tsym) != null) { |
1151 // compare return types |
1172 result &= MostSpecificCheckContext.super.compatible(t, s, warn); |
1152 Type ret_t = desc_t.getReturnType(); |
1173 } else if (!desc_s.getReturnType().hasTag(VOID)) { |
1153 Type ret_s = desc_s.getReturnType(); |
1174 //perform structural comparison |
1154 if (ret_s.hasTag(VOID)) { |
1175 Type ret_t = desc_t.getReturnType(); |
1155 result &= true; |
1176 Type ret_s = desc_s.getReturnType(); |
1156 } else if (ret_t.hasTag(VOID)) { |
1177 result &= ((tree.refPolyKind == PolyKind.STANDALONE) |
1157 result &= false; |
1178 ? standaloneMostSpecific(ret_t, ret_s, tree.sym.type.getReturnType(), warn) |
1158 } else if (ret_t.isPrimitive() != ret_s.isPrimitive()) { |
1179 : polyMostSpecific(ret_t, ret_s, warn)); |
1159 boolean retValIsPrimitive = |
1180 } else { |
1160 tree.refPolyKind == PolyKind.STANDALONE && |
1181 return; |
1161 tree.sym.type.getReturnType().isPrimitive(); |
1182 } |
1162 result &= (retValIsPrimitive == ret_t.isPrimitive()) && |
|
1163 (retValIsPrimitive != ret_s.isPrimitive()); |
|
1164 } else { |
|
1165 result &= MostSpecificCheckContext.super.compatible(ret_t, ret_s, warn); |
1183 } |
1166 } |
1184 } else { |
|
1185 result &= false; |
|
1186 } |
1167 } |
1187 } |
1168 } |
1188 |
1169 |
1189 @Override |
1170 @Override |
1190 public void visitLambda(JCLambda tree) { |
1171 public void visitLambda(JCLambda tree) { |
1191 if (types.isFunctionalInterface(t.tsym) && |
1172 Type desc_t = types.findDescriptorType(t); |
1192 types.isFunctionalInterface(s.tsym)) { |
1173 Type desc_s = types.findDescriptorType(s); |
1193 Type desc_t = types.findDescriptorType(t); |
1174 // use inference variables here for more-specific inference (18.5.4) |
1194 Type desc_s = types.findDescriptorType(s); |
1175 if (!types.isSameTypes(desc_t.getParameterTypes(), |
1195 if (types.isSameTypes(desc_t.getParameterTypes(), |
1176 inferenceContext().asUndetVars(desc_s.getParameterTypes()))) { |
1196 inferenceContext().asUndetVars(desc_s.getParameterTypes()))) { |
1177 result &= false; |
1197 if (types.asSuper(t, s.tsym) != null || |
1178 } else { |
1198 types.asSuper(s, t.tsym) != null) { |
1179 // compare return types |
1199 result &= MostSpecificCheckContext.super.compatible(t, s, warn); |
1180 Type ret_t = desc_t.getReturnType(); |
1200 } else if (!desc_s.getReturnType().hasTag(VOID)) { |
1181 Type ret_s = desc_s.getReturnType(); |
1201 //perform structural comparison |
1182 if (ret_s.hasTag(VOID)) { |
1202 Type ret_t = desc_t.getReturnType(); |
1183 result &= true; |
1203 Type ret_s = desc_s.getReturnType(); |
1184 } else if (ret_t.hasTag(VOID)) { |
1204 scanLambdaBody(tree, ret_t, ret_s); |
1185 result &= false; |
1205 } else { |
1186 } else if (unrelatedFunctionalInterfaces(ret_t, ret_s)) { |
1206 return; |
1187 for (JCExpression expr : lambdaResults(tree)) { |
|
1188 result &= functionalInterfaceMostSpecific(ret_t, ret_s, expr, warn); |
1207 } |
1189 } |
|
1190 } else if (ret_t.isPrimitive() != ret_s.isPrimitive()) { |
|
1191 for (JCExpression expr : lambdaResults(tree)) { |
|
1192 boolean retValIsPrimitive = expr.isStandalone() && expr.type.isPrimitive(); |
|
1193 result &= (retValIsPrimitive == ret_t.isPrimitive()) && |
|
1194 (retValIsPrimitive != ret_s.isPrimitive()); |
|
1195 } |
|
1196 } else { |
|
1197 result &= MostSpecificCheckContext.super.compatible(ret_t, ret_s, warn); |
1208 } |
1198 } |
|
1199 } |
|
1200 } |
|
1201 //where |
|
1202 |
|
1203 private List<JCExpression> lambdaResults(JCLambda lambda) { |
|
1204 if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) { |
|
1205 return List.of((JCExpression) lambda.body); |
1209 } else { |
1206 } else { |
1210 result &= false; |
1207 final ListBuffer<JCExpression> buffer = new ListBuffer<>(); |
1211 } |
|
1212 } |
|
1213 //where |
|
1214 |
|
1215 void scanLambdaBody(JCLambda lambda, final Type t, final Type s) { |
|
1216 if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) { |
|
1217 result &= MostSpecificCheckContext.this.mostSpecific(t, s, lambda.body, warn); |
|
1218 } else { |
|
1219 DeferredAttr.LambdaReturnScanner lambdaScanner = |
1208 DeferredAttr.LambdaReturnScanner lambdaScanner = |
1220 new DeferredAttr.LambdaReturnScanner() { |
1209 new DeferredAttr.LambdaReturnScanner() { |
1221 @Override |
1210 @Override |
1222 public void visitReturn(JCReturn tree) { |
1211 public void visitReturn(JCReturn tree) { |
1223 if (tree.expr != null) { |
1212 if (tree.expr != null) { |
1224 result &= MostSpecificCheckContext.this.mostSpecific(t, s, tree.expr, warn); |
1213 buffer.append(tree.expr); |
1225 } |
1214 } |
1226 } |
1215 } |
1227 }; |
1216 }; |
1228 lambdaScanner.scan(lambda.body); |
1217 lambdaScanner.scan(lambda.body); |
|
1218 return buffer.toList(); |
1229 } |
1219 } |
1230 } |
1220 } |
1231 } |
1221 } |
|
1222 |
1232 } |
1223 } |
1233 |
1224 |
1234 public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) { |
1225 public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) { |
1235 Assert.error("Cannot get here!"); |
1226 Assert.error("Cannot get here!"); |
1236 return null; |
1227 return null; |