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

changeset 2395
9c577131ffa6
parent 2392
73cbce40a149
child 2400
0e026d3f2786
equal deleted inserted replaced
2394:89cefe38ecaf 2395:9c577131ffa6
93 Types types; 93 Types types;
94 JCDiagnostic.Factory diags; 94 JCDiagnostic.Factory diags;
95 public final boolean boxingEnabled; 95 public final boolean boxingEnabled;
96 public final boolean varargsEnabled; 96 public final boolean varargsEnabled;
97 public final boolean allowMethodHandles; 97 public final boolean allowMethodHandles;
98 public final boolean allowStructuralMostSpecific; 98 public final boolean allowFunctionalInterfaceMostSpecific;
99 private final boolean debugResolve; 99 private final boolean debugResolve;
100 private final boolean compactMethodDiags; 100 private final boolean compactMethodDiags;
101 final EnumSet<VerboseResolutionMode> verboseResolutionMode; 101 final EnumSet<VerboseResolutionMode> verboseResolutionMode;
102 102
103 Scope polymorphicSignatureScope; 103 Scope polymorphicSignatureScope;
134 compactMethodDiags = options.isSet(Option.XDIAGS, "compact") || 134 compactMethodDiags = options.isSet(Option.XDIAGS, "compact") ||
135 options.isUnset(Option.XDIAGS) && options.isUnset("rawDiagnostics"); 135 options.isUnset(Option.XDIAGS) && options.isUnset("rawDiagnostics");
136 verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options); 136 verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
137 Target target = Target.instance(context); 137 Target target = Target.instance(context);
138 allowMethodHandles = target.hasMethodHandles(); 138 allowMethodHandles = target.hasMethodHandles();
139 allowStructuralMostSpecific = source.allowStructuralMostSpecific(); 139 allowFunctionalInterfaceMostSpecific = source.allowFunctionalInterfaceMostSpecific();
140 polymorphicSignatureScope = new Scope(syms.noSymbol); 140 polymorphicSignatureScope = new Scope(syms.noSymbol);
141 141
142 inapplicableMethodException = new InapplicableMethodException(diags); 142 inapplicableMethodException = new InapplicableMethodException(diags);
143 } 143 }
144 144
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;

mercurial