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; |