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

changeset 1510
7873d37f5b37
parent 1498
1afdf1f1472b
child 1521
71f35e4b93a5
equal deleted inserted replaced
1509:1985e35e97b2 1510:7873d37f5b37
39 import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate; 39 import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate;
40 import com.sun.tools.javac.jvm.*; 40 import com.sun.tools.javac.jvm.*;
41 import com.sun.tools.javac.tree.*; 41 import com.sun.tools.javac.tree.*;
42 import com.sun.tools.javac.tree.JCTree.*; 42 import com.sun.tools.javac.tree.JCTree.*;
43 import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind; 43 import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
44 import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*;
44 import com.sun.tools.javac.util.*; 45 import com.sun.tools.javac.util.*;
45 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; 46 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
46 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 47 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
47 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; 48 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType;
48 49
90 JCDiagnostic.Factory diags; 91 JCDiagnostic.Factory diags;
91 public final boolean boxingEnabled; // = source.allowBoxing(); 92 public final boolean boxingEnabled; // = source.allowBoxing();
92 public final boolean varargsEnabled; // = source.allowVarargs(); 93 public final boolean varargsEnabled; // = source.allowVarargs();
93 public final boolean allowMethodHandles; 94 public final boolean allowMethodHandles;
94 public final boolean allowDefaultMethods; 95 public final boolean allowDefaultMethods;
96 public final boolean allowStructuralMostSpecific;
95 private final boolean debugResolve; 97 private final boolean debugResolve;
96 final EnumSet<VerboseResolutionMode> verboseResolutionMode; 98 final EnumSet<VerboseResolutionMode> verboseResolutionMode;
97 99
98 Scope polymorphicSignatureScope; 100 Scope polymorphicSignatureScope;
99 101
125 debugResolve = options.isSet("debugresolve"); 127 debugResolve = options.isSet("debugresolve");
126 verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options); 128 verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
127 Target target = Target.instance(context); 129 Target target = Target.instance(context);
128 allowMethodHandles = target.hasMethodHandles(); 130 allowMethodHandles = target.hasMethodHandles();
129 allowDefaultMethods = source.allowDefaultMethods(); 131 allowDefaultMethods = source.allowDefaultMethods();
132 allowStructuralMostSpecific = source.allowStructuralMostSpecific();
130 polymorphicSignatureScope = new Scope(syms.noSymbol); 133 polymorphicSignatureScope = new Scope(syms.noSymbol);
131 134
132 inapplicableMethodException = new InapplicableMethodException(diags); 135 inapplicableMethodException = new InapplicableMethodException(diags);
133 } 136 }
134 137
833 protected ResultInfo dup(CheckContext newContext) { 836 protected ResultInfo dup(CheckContext newContext) {
834 return new MethodResultInfo(pt, newContext); 837 return new MethodResultInfo(pt, newContext);
835 } 838 }
836 } 839 }
837 840
841 /**
842 * Most specific method applicability routine. Given a list of actual types A,
843 * a list of formal types F1, and a list of formal types F2, the routine determines
844 * as to whether the types in F1 can be considered more specific than those in F2 w.r.t.
845 * argument types A.
846 */
847 class MostSpecificCheck implements MethodCheck {
848
849 boolean strict;
850 List<Type> actuals;
851
852 MostSpecificCheck(boolean strict, List<Type> actuals) {
853 this.strict = strict;
854 this.actuals = actuals;
855 }
856
857 @Override
858 public void argumentsAcceptable(final Env<AttrContext> env,
859 DeferredAttrContext deferredAttrContext,
860 List<Type> formals1,
861 List<Type> formals2,
862 Warner warn) {
863 formals2 = adjustArgs(formals2, deferredAttrContext.msym, formals1.length(), deferredAttrContext.phase.isVarargsRequired());
864 while (formals2.nonEmpty()) {
865 ResultInfo mresult = methodCheckResult(formals2.head, deferredAttrContext, warn, actuals.head);
866 mresult.check(null, formals1.head);
867 formals1 = formals1.tail;
868 formals2 = formals2.tail;
869 actuals = actuals.isEmpty() ? actuals : actuals.tail;
870 }
871 }
872
873 /**
874 * Create a method check context to be used during the most specific applicability check
875 */
876 ResultInfo methodCheckResult(Type to, DeferredAttr.DeferredAttrContext deferredAttrContext,
877 Warner rsWarner, Type actual) {
878 return attr.new ResultInfo(Kinds.VAL, to,
879 new MostSpecificCheckContext(strict, deferredAttrContext, rsWarner, actual));
880 }
881
882 /**
883 * Subclass of method check context class that implements most specific
884 * method conversion. If the actual type under analysis is a deferred type
885 * a full blown structural analysis is carried out.
886 */
887 class MostSpecificCheckContext extends MethodCheckContext {
888
889 Type actual;
890
891 public MostSpecificCheckContext(boolean strict, DeferredAttrContext deferredAttrContext, Warner rsWarner, Type actual) {
892 super(strict, deferredAttrContext, rsWarner);
893 this.actual = actual;
894 }
895
896 public boolean compatible(Type found, Type req, Warner warn) {
897 if (!allowStructuralMostSpecific || actual == null) {
898 return super.compatible(found, req, warn);
899 } else {
900 switch (actual.getTag()) {
901 case DEFERRED:
902 DeferredType dt = (DeferredType) actual;
903 DeferredType.SpeculativeCache.Entry e = dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase);
904 return (e == null || e.speculativeTree == deferredAttr.stuckTree)
905 ? false : mostSpecific(found, req, e.speculativeTree, warn);
906 default:
907 return standaloneMostSpecific(found, req, actual, warn);
908 }
909 }
910 }
911
912 private boolean mostSpecific(Type t, Type s, JCTree tree, Warner warn) {
913 MostSpecificChecker msc = new MostSpecificChecker(t, s, warn);
914 msc.scan(tree);
915 return msc.result;
916 }
917
918 boolean polyMostSpecific(Type t1, Type t2, Warner warn) {
919 return (!t1.isPrimitive() && t2.isPrimitive())
920 ? true : super.compatible(t1, t2, warn);
921 }
922
923 boolean standaloneMostSpecific(Type t1, Type t2, Type exprType, Warner warn) {
924 return (exprType.isPrimitive() == t1.isPrimitive()
925 && exprType.isPrimitive() != t2.isPrimitive())
926 ? true : super.compatible(t1, t2, warn);
927 }
928
929 /**
930 * Structural checker for most specific.
931 */
932 class MostSpecificChecker extends DeferredAttr.PolyScanner {
933
934 final Type t;
935 final Type s;
936 final Warner warn;
937 boolean result;
938
939 MostSpecificChecker(Type t, Type s, Warner warn) {
940 this.t = t;
941 this.s = s;
942 this.warn = warn;
943 result = true;
944 }
945
946 @Override
947 void skip(JCTree tree) {
948 result &= standaloneMostSpecific(t, s, tree.type, warn);
949 }
950
951 @Override
952 public void visitConditional(JCConditional tree) {
953 if (tree.polyKind == PolyKind.STANDALONE) {
954 result &= standaloneMostSpecific(t, s, tree.type, warn);
955 } else {
956 super.visitConditional(tree);
957 }
958 }
959
960 @Override
961 public void visitApply(JCMethodInvocation tree) {
962 result &= (tree.polyKind == PolyKind.STANDALONE)
963 ? standaloneMostSpecific(t, s, tree.type, warn)
964 : polyMostSpecific(t, s, warn);
965 }
966
967 @Override
968 public void visitNewClass(JCNewClass tree) {
969 result &= (tree.polyKind == PolyKind.STANDALONE)
970 ? standaloneMostSpecific(t, s, tree.type, warn)
971 : polyMostSpecific(t, s, warn);
972 }
973
974 @Override
975 public void visitReference(JCMemberReference tree) {
976 if (types.isFunctionalInterface(t.tsym) &&
977 types.isFunctionalInterface(s.tsym) &&
978 types.asSuper(t, s.tsym) == null &&
979 types.asSuper(s, t.tsym) == null) {
980 Type desc_t = types.findDescriptorType(t);
981 Type desc_s = types.findDescriptorType(s);
982 if (types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) {
983 if (!desc_s.getReturnType().hasTag(VOID)) {
984 //perform structural comparison
985 Type ret_t = desc_t.getReturnType();
986 Type ret_s = desc_s.getReturnType();
987 result &= ((tree.refPolyKind == PolyKind.STANDALONE)
988 ? standaloneMostSpecific(ret_t, ret_s, tree.type, warn)
989 : polyMostSpecific(ret_t, ret_s, warn));
990 } else {
991 return;
992 }
993 } else {
994 result &= false;
995 }
996 } else {
997 result &= MostSpecificCheckContext.super.compatible(t, s, warn);
998 }
999 }
1000
1001 @Override
1002 public void visitLambda(JCLambda tree) {
1003 if (types.isFunctionalInterface(t.tsym) &&
1004 types.isFunctionalInterface(s.tsym) &&
1005 types.asSuper(t, s.tsym) == null &&
1006 types.asSuper(s, t.tsym) == null) {
1007 Type desc_t = types.findDescriptorType(t);
1008 Type desc_s = types.findDescriptorType(s);
1009 if (tree.paramKind == JCLambda.ParameterKind.EXPLICIT
1010 || types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) {
1011 if (!desc_s.getReturnType().hasTag(VOID)) {
1012 //perform structural comparison
1013 Type ret_t = desc_t.getReturnType();
1014 Type ret_s = desc_s.getReturnType();
1015 scanLambdaBody(tree, ret_t, ret_s);
1016 } else {
1017 return;
1018 }
1019 } else {
1020 result &= false;
1021 }
1022 } else {
1023 result &= MostSpecificCheckContext.super.compatible(t, s, warn);
1024 }
1025 }
1026 //where
1027
1028 void scanLambdaBody(JCLambda lambda, final Type t, final Type s) {
1029 if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
1030 result &= MostSpecificCheckContext.this.mostSpecific(t, s, lambda.body, warn);
1031 } else {
1032 DeferredAttr.LambdaReturnScanner lambdaScanner =
1033 new DeferredAttr.LambdaReturnScanner() {
1034 @Override
1035 public void visitReturn(JCReturn tree) {
1036 if (tree.expr != null) {
1037 result &= MostSpecificCheckContext.this.mostSpecific(t, s, tree.expr, warn);
1038 }
1039 }
1040 };
1041 lambdaScanner.scan(lambda.body);
1042 }
1043 }
1044 }
1045 }
1046 }
1047
838 public static class InapplicableMethodException extends RuntimeException { 1048 public static class InapplicableMethodException extends RuntimeException {
839 private static final long serialVersionUID = 0; 1049 private static final long serialVersionUID = 0;
840 1050
841 JCDiagnostic diagnostic; 1051 JCDiagnostic diagnostic;
842 JCDiagnostic.Factory diags; 1052 JCDiagnostic.Factory diags;
1140 throw new AssertionError(); 1350 throw new AssertionError();
1141 } 1351 }
1142 } 1352 }
1143 //where 1353 //where
1144 private boolean signatureMoreSpecific(List<Type> actuals, Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean allowBoxing, boolean useVarargs) { 1354 private boolean signatureMoreSpecific(List<Type> actuals, Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean allowBoxing, boolean useVarargs) {
1145 Symbol m12 = adjustVarargs(m1, m2, useVarargs); 1355 noteWarner.clear();
1146 Symbol m22 = adjustVarargs(m2, m1, useVarargs); 1356 int maxLength = Math.max(
1147 Type mtype1 = types.memberType(site, m12); 1357 Math.max(m1.type.getParameterTypes().length(), actuals.length()),
1148 Type mtype2 = types.memberType(site, m22); 1358 m2.type.getParameterTypes().length());
1149 1359 Type mst = instantiate(env, site, m2, null,
1150 //check if invocation is more specific 1360 adjustArgs(types.lowerBounds(types.memberType(site, m1).getParameterTypes()), m1, maxLength, useVarargs), null,
1151 if (invocationMoreSpecific(env, site, m22, mtype1.getParameterTypes(), allowBoxing, useVarargs)) { 1361 allowBoxing, useVarargs, new MostSpecificCheck(!allowBoxing, actuals), noteWarner);
1152 return true; 1362 return mst != null &&
1153 } 1363 !noteWarner.hasLint(Lint.LintCategory.UNCHECKED);
1154 1364 }
1155 //perform structural check 1365 private List<Type> adjustArgs(List<Type> args, Symbol msym, int length, boolean allowVarargs) {
1156 1366 if ((msym.flags() & VARARGS) != 0 && allowVarargs) {
1157 List<Type> formals1 = mtype1.getParameterTypes(); 1367 Type varargsElem = types.elemtype(args.last());
1158 Type lastFormal1 = formals1.last(); 1368 if (varargsElem == null) {
1159 List<Type> formals2 = mtype2.getParameterTypes(); 1369 Assert.error("Bad varargs = " + args.last() + " " + msym);
1160 Type lastFormal2 = formals2.last(); 1370 }
1161 ListBuffer<Type> newFormals = ListBuffer.lb(); 1371 List<Type> newArgs = args.reverse().tail.prepend(varargsElem).reverse();
1162 1372 while (newArgs.length() < length) {
1163 boolean hasStructuralPoly = false; 1373 newArgs = newArgs.append(newArgs.last());
1164 for (Type actual : actuals) { 1374 }
1165 //perform formal argument adaptation in case actuals > formals (varargs) 1375 return newArgs;
1166 Type f1 = formals1.isEmpty() ?
1167 lastFormal1 : formals1.head;
1168 Type f2 = formals2.isEmpty() ?
1169 lastFormal2 : formals2.head;
1170
1171 //is this a structural actual argument?
1172 boolean isStructuralPoly = actual.hasTag(DEFERRED) &&
1173 (((DeferredType)actual).tree.hasTag(LAMBDA) ||
1174 ((DeferredType)actual).tree.hasTag(REFERENCE));
1175
1176 Type newFormal = f1;
1177
1178 if (isStructuralPoly) {
1179 //for structural arguments only - check that corresponding formals
1180 //are related - if so replace formal with <null>
1181 hasStructuralPoly = true;
1182 DeferredType dt = (DeferredType)actual;
1183 Type t1 = deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, m1, currentResolutionContext.step).apply(dt);
1184 Type t2 = deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, m2, currentResolutionContext.step).apply(dt);
1185 if (t1.isErroneous() || t2.isErroneous() || !isStructuralSubtype(t1, t2)) {
1186 //not structural subtypes - simply fail
1187 return false;
1188 } else {
1189 newFormal = syms.botType;
1190 }
1191 }
1192
1193 newFormals.append(newFormal);
1194 if (newFormals.length() > mtype2.getParameterTypes().length()) {
1195 //expand m2's type so as to fit the new formal arity (varargs)
1196 m22.type = types.createMethodTypeWithParameters(m22.type, m22.type.getParameterTypes().append(f2));
1197 }
1198
1199 formals1 = formals1.isEmpty() ? formals1 : formals1.tail;
1200 formals2 = formals2.isEmpty() ? formals2 : formals2.tail;
1201 }
1202
1203 if (!hasStructuralPoly) {
1204 //if no structural actual was found, we're done
1205 return false;
1206 }
1207 //perform additional adaptation if actuals < formals (varargs)
1208 for (Type t : formals1) {
1209 newFormals.append(t);
1210 }
1211 //check if invocation (with tweaked args) is more specific
1212 return invocationMoreSpecific(env, site, m22, newFormals.toList(), allowBoxing, useVarargs);
1213 }
1214 //where
1215 private boolean invocationMoreSpecific(Env<AttrContext> env, Type site, Symbol m2, List<Type> argtypes1, boolean allowBoxing, boolean useVarargs) {
1216 MethodResolutionContext prevContext = currentResolutionContext;
1217 try {
1218 currentResolutionContext = new MethodResolutionContext();
1219 currentResolutionContext.step = allowBoxing ? BOX : BASIC;
1220 noteWarner.clear();
1221 Type mst = instantiate(env, site, m2, null,
1222 types.lowerBounds(argtypes1), null,
1223 allowBoxing, false, resolveMethodCheck, noteWarner);
1224 return mst != null &&
1225 !noteWarner.hasLint(Lint.LintCategory.UNCHECKED);
1226 } finally {
1227 currentResolutionContext = prevContext;
1228 }
1229 }
1230 //where
1231 private Symbol adjustVarargs(Symbol to, Symbol from, boolean useVarargs) {
1232 List<Type> fromArgs = from.type.getParameterTypes();
1233 List<Type> toArgs = to.type.getParameterTypes();
1234 if (useVarargs &&
1235 (from.flags() & VARARGS) != 0 &&
1236 (to.flags() & VARARGS) != 0) {
1237 Type varargsTypeFrom = fromArgs.last();
1238 Type varargsTypeTo = toArgs.last();
1239 ListBuffer<Type> args = ListBuffer.lb();
1240 if (toArgs.length() < fromArgs.length()) {
1241 //if we are checking a varargs method 'from' against another varargs
1242 //method 'to' (where arity of 'to' < arity of 'from') then expand signature
1243 //of 'to' to 'fit' arity of 'from' (this means adding fake formals to 'to'
1244 //until 'to' signature has the same arity as 'from')
1245 while (fromArgs.head != varargsTypeFrom) {
1246 args.append(toArgs.head == varargsTypeTo ? types.elemtype(varargsTypeTo) : toArgs.head);
1247 fromArgs = fromArgs.tail;
1248 toArgs = toArgs.head == varargsTypeTo ?
1249 toArgs :
1250 toArgs.tail;
1251 }
1252 } else {
1253 //formal argument list is same as original list where last
1254 //argument (array type) is removed
1255 args.appendList(toArgs.reverse().tail.reverse());
1256 }
1257 //append varargs element type as last synthetic formal
1258 args.append(types.elemtype(varargsTypeTo));
1259 Type mtype = types.createMethodTypeWithParameters(to.type, args.toList());
1260 return new MethodSymbol(to.flags_field & ~VARARGS, to.name, mtype, to.owner);
1261 } else { 1376 } else {
1262 return to; 1377 return args;
1263 } 1378 }
1264 }
1265 //where
1266 boolean isStructuralSubtype(Type s, Type t) {
1267
1268 Type ret_s = types.findDescriptorType(s).getReturnType();
1269 Type ret_t = types.findDescriptorType(t).getReturnType();
1270
1271 //covariant most specific check for function descriptor return type
1272 if (!types.isSubtype(ret_s, ret_t)) {
1273 return false;
1274 }
1275
1276 List<Type> args_s = types.findDescriptorType(s).getParameterTypes();
1277 List<Type> args_t = types.findDescriptorType(t).getParameterTypes();
1278
1279 //arity must be identical
1280 if (args_s.length() != args_t.length()) {
1281 return false;
1282 }
1283
1284 //invariant most specific check for function descriptor parameter types
1285 if (!types.isSameTypes(args_t, args_s)) {
1286 return false;
1287 }
1288
1289 return true;
1290 } 1379 }
1291 //where 1380 //where
1292 Type mostSpecificReturnType(Type mt1, Type mt2) { 1381 Type mostSpecificReturnType(Type mt1, Type mt2) {
1293 Type rt1 = mt1.getReturnType(); 1382 Type rt1 = mt1.getReturnType();
1294 Type rt2 = mt2.getReturnType(); 1383 Type rt2 = mt2.getReturnType();

mercurial