691 |
693 |
692 Type varargsFormal = useVarargs ? formals.last() : null; |
694 Type varargsFormal = useVarargs ? formals.last() : null; |
693 |
695 |
694 if (varargsFormal == null && |
696 if (varargsFormal == null && |
695 argtypes.size() != formals.size()) { |
697 argtypes.size() != formals.size()) { |
696 report(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args |
698 reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args |
697 } |
699 } |
698 |
700 |
699 while (argtypes.nonEmpty() && formals.head != varargsFormal) { |
701 while (argtypes.nonEmpty() && formals.head != varargsFormal) { |
700 ResultInfo mresult = methodCheckResult(false, formals.head, deferredAttrContext, warn); |
702 ResultInfo mresult = methodCheckResult(false, formals.head, deferredAttrContext, warn); |
701 mresult.check(null, argtypes.head); |
703 mresult.check(null, argtypes.head); |
702 argtypes = argtypes.tail; |
704 argtypes = argtypes.tail; |
703 formals = formals.tail; |
705 formals = formals.tail; |
704 } |
706 } |
705 |
707 |
706 if (formals.head != varargsFormal) { |
708 if (formals.head != varargsFormal) { |
707 report(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args |
709 reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args |
708 } |
710 } |
709 |
711 |
710 if (useVarargs) { |
712 if (useVarargs) { |
711 //note: if applicability check is triggered by most specific test, |
713 //note: if applicability check is triggered by most specific test, |
712 //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5) |
714 //the last argument of a varargs is _not_ an array type (see JLS 15.12.2.5) |
830 } |
832 } |
831 |
833 |
832 @Override |
834 @Override |
833 protected ResultInfo dup(CheckContext newContext) { |
835 protected ResultInfo dup(CheckContext newContext) { |
834 return new MethodResultInfo(pt, newContext); |
836 return new MethodResultInfo(pt, newContext); |
|
837 } |
|
838 } |
|
839 |
|
840 /** |
|
841 * Most specific method applicability routine. Given a list of actual types A, |
|
842 * a list of formal types F1, and a list of formal types F2, the routine determines |
|
843 * as to whether the types in F1 can be considered more specific than those in F2 w.r.t. |
|
844 * argument types A. |
|
845 */ |
|
846 class MostSpecificCheck implements MethodCheck { |
|
847 |
|
848 boolean strict; |
|
849 List<Type> actuals; |
|
850 |
|
851 MostSpecificCheck(boolean strict, List<Type> actuals) { |
|
852 this.strict = strict; |
|
853 this.actuals = actuals; |
|
854 } |
|
855 |
|
856 @Override |
|
857 public void argumentsAcceptable(final Env<AttrContext> env, |
|
858 DeferredAttrContext deferredAttrContext, |
|
859 List<Type> formals1, |
|
860 List<Type> formals2, |
|
861 Warner warn) { |
|
862 formals2 = adjustArgs(formals2, deferredAttrContext.msym, formals1.length(), deferredAttrContext.phase.isVarargsRequired()); |
|
863 while (formals2.nonEmpty()) { |
|
864 ResultInfo mresult = methodCheckResult(formals2.head, deferredAttrContext, warn, actuals.head); |
|
865 mresult.check(null, formals1.head); |
|
866 formals1 = formals1.tail; |
|
867 formals2 = formals2.tail; |
|
868 actuals = actuals.isEmpty() ? actuals : actuals.tail; |
|
869 } |
|
870 } |
|
871 |
|
872 /** |
|
873 * Create a method check context to be used during the most specific applicability check |
|
874 */ |
|
875 ResultInfo methodCheckResult(Type to, DeferredAttr.DeferredAttrContext deferredAttrContext, |
|
876 Warner rsWarner, Type actual) { |
|
877 return attr.new ResultInfo(Kinds.VAL, to, |
|
878 new MostSpecificCheckContext(strict, deferredAttrContext, rsWarner, actual)); |
|
879 } |
|
880 |
|
881 /** |
|
882 * Subclass of method check context class that implements most specific |
|
883 * method conversion. If the actual type under analysis is a deferred type |
|
884 * a full blown structural analysis is carried out. |
|
885 */ |
|
886 class MostSpecificCheckContext extends MethodCheckContext { |
|
887 |
|
888 Type actual; |
|
889 |
|
890 public MostSpecificCheckContext(boolean strict, DeferredAttrContext deferredAttrContext, Warner rsWarner, Type actual) { |
|
891 super(strict, deferredAttrContext, rsWarner); |
|
892 this.actual = actual; |
|
893 } |
|
894 |
|
895 public boolean compatible(Type found, Type req, Warner warn) { |
|
896 if (!allowStructuralMostSpecific || actual == null) { |
|
897 return super.compatible(found, req, warn); |
|
898 } else { |
|
899 switch (actual.getTag()) { |
|
900 case DEFERRED: |
|
901 DeferredType dt = (DeferredType) actual; |
|
902 DeferredType.SpeculativeCache.Entry e = dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase); |
|
903 return (e == null || e.speculativeTree == deferredAttr.stuckTree) |
|
904 ? false : mostSpecific(found, req, e.speculativeTree, warn); |
|
905 default: |
|
906 return standaloneMostSpecific(found, req, actual, warn); |
|
907 } |
|
908 } |
|
909 } |
|
910 |
|
911 private boolean mostSpecific(Type t, Type s, JCTree tree, Warner warn) { |
|
912 MostSpecificChecker msc = new MostSpecificChecker(t, s, warn); |
|
913 msc.scan(tree); |
|
914 return msc.result; |
|
915 } |
|
916 |
|
917 boolean polyMostSpecific(Type t1, Type t2, Warner warn) { |
|
918 return (!t1.isPrimitive() && t2.isPrimitive()) |
|
919 ? true : super.compatible(t1, t2, warn); |
|
920 } |
|
921 |
|
922 boolean standaloneMostSpecific(Type t1, Type t2, Type exprType, Warner warn) { |
|
923 return (exprType.isPrimitive() == t1.isPrimitive() |
|
924 && exprType.isPrimitive() != t2.isPrimitive()) |
|
925 ? true : super.compatible(t1, t2, warn); |
|
926 } |
|
927 |
|
928 /** |
|
929 * Structural checker for most specific. |
|
930 */ |
|
931 class MostSpecificChecker extends DeferredAttr.PolyScanner { |
|
932 |
|
933 final Type t; |
|
934 final Type s; |
|
935 final Warner warn; |
|
936 boolean result; |
|
937 |
|
938 MostSpecificChecker(Type t, Type s, Warner warn) { |
|
939 this.t = t; |
|
940 this.s = s; |
|
941 this.warn = warn; |
|
942 result = true; |
|
943 } |
|
944 |
|
945 @Override |
|
946 void skip(JCTree tree) { |
|
947 result &= standaloneMostSpecific(t, s, tree.type, warn); |
|
948 } |
|
949 |
|
950 @Override |
|
951 public void visitConditional(JCConditional tree) { |
|
952 if (tree.polyKind == PolyKind.STANDALONE) { |
|
953 result &= standaloneMostSpecific(t, s, tree.type, warn); |
|
954 } else { |
|
955 super.visitConditional(tree); |
|
956 } |
|
957 } |
|
958 |
|
959 @Override |
|
960 public void visitApply(JCMethodInvocation tree) { |
|
961 result &= (tree.polyKind == PolyKind.STANDALONE) |
|
962 ? standaloneMostSpecific(t, s, tree.type, warn) |
|
963 : polyMostSpecific(t, s, warn); |
|
964 } |
|
965 |
|
966 @Override |
|
967 public void visitNewClass(JCNewClass tree) { |
|
968 result &= (tree.polyKind == PolyKind.STANDALONE) |
|
969 ? standaloneMostSpecific(t, s, tree.type, warn) |
|
970 : polyMostSpecific(t, s, warn); |
|
971 } |
|
972 |
|
973 @Override |
|
974 public void visitReference(JCMemberReference tree) { |
|
975 if (types.isFunctionalInterface(t.tsym) && |
|
976 types.isFunctionalInterface(s.tsym) && |
|
977 types.asSuper(t, s.tsym) == null && |
|
978 types.asSuper(s, t.tsym) == null) { |
|
979 Type desc_t = types.findDescriptorType(t); |
|
980 Type desc_s = types.findDescriptorType(s); |
|
981 if (types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) { |
|
982 if (!desc_s.getReturnType().hasTag(VOID)) { |
|
983 //perform structural comparison |
|
984 Type ret_t = desc_t.getReturnType(); |
|
985 Type ret_s = desc_s.getReturnType(); |
|
986 result &= ((tree.refPolyKind == PolyKind.STANDALONE) |
|
987 ? standaloneMostSpecific(ret_t, ret_s, tree.type, warn) |
|
988 : polyMostSpecific(ret_t, ret_s, warn)); |
|
989 } else { |
|
990 return; |
|
991 } |
|
992 } else { |
|
993 result &= false; |
|
994 } |
|
995 } else { |
|
996 result &= MostSpecificCheckContext.super.compatible(t, s, warn); |
|
997 } |
|
998 } |
|
999 |
|
1000 @Override |
|
1001 public void visitLambda(JCLambda tree) { |
|
1002 if (types.isFunctionalInterface(t.tsym) && |
|
1003 types.isFunctionalInterface(s.tsym) && |
|
1004 types.asSuper(t, s.tsym) == null && |
|
1005 types.asSuper(s, t.tsym) == null) { |
|
1006 Type desc_t = types.findDescriptorType(t); |
|
1007 Type desc_s = types.findDescriptorType(s); |
|
1008 if (tree.paramKind == JCLambda.ParameterKind.EXPLICIT |
|
1009 || types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) { |
|
1010 if (!desc_s.getReturnType().hasTag(VOID)) { |
|
1011 //perform structural comparison |
|
1012 Type ret_t = desc_t.getReturnType(); |
|
1013 Type ret_s = desc_s.getReturnType(); |
|
1014 scanLambdaBody(tree, ret_t, ret_s); |
|
1015 } else { |
|
1016 return; |
|
1017 } |
|
1018 } else { |
|
1019 result &= false; |
|
1020 } |
|
1021 } else { |
|
1022 result &= MostSpecificCheckContext.super.compatible(t, s, warn); |
|
1023 } |
|
1024 } |
|
1025 //where |
|
1026 |
|
1027 void scanLambdaBody(JCLambda lambda, final Type t, final Type s) { |
|
1028 if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) { |
|
1029 result &= MostSpecificCheckContext.this.mostSpecific(t, s, lambda.body, warn); |
|
1030 } else { |
|
1031 DeferredAttr.LambdaReturnScanner lambdaScanner = |
|
1032 new DeferredAttr.LambdaReturnScanner() { |
|
1033 @Override |
|
1034 public void visitReturn(JCReturn tree) { |
|
1035 if (tree.expr != null) { |
|
1036 result &= MostSpecificCheckContext.this.mostSpecific(t, s, tree.expr, warn); |
|
1037 } |
|
1038 } |
|
1039 }; |
|
1040 lambdaScanner.scan(lambda.body); |
|
1041 } |
|
1042 } |
|
1043 } |
835 } |
1044 } |
836 } |
1045 } |
837 |
1046 |
838 public static class InapplicableMethodException extends RuntimeException { |
1047 public static class InapplicableMethodException extends RuntimeException { |
839 private static final long serialVersionUID = 0; |
1048 private static final long serialVersionUID = 0; |
1140 throw new AssertionError(); |
1349 throw new AssertionError(); |
1141 } |
1350 } |
1142 } |
1351 } |
1143 //where |
1352 //where |
1144 private boolean signatureMoreSpecific(List<Type> actuals, Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean allowBoxing, boolean useVarargs) { |
1353 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); |
1354 noteWarner.clear(); |
1146 Symbol m22 = adjustVarargs(m2, m1, useVarargs); |
1355 int maxLength = Math.max( |
1147 Type mtype1 = types.memberType(site, m12); |
1356 Math.max(m1.type.getParameterTypes().length(), actuals.length()), |
1148 Type mtype2 = types.memberType(site, m22); |
1357 m2.type.getParameterTypes().length()); |
1149 |
1358 Type mst = instantiate(env, site, m2, null, |
1150 //check if invocation is more specific |
1359 adjustArgs(types.lowerBounds(types.memberType(site, m1).getParameterTypes()), m1, maxLength, useVarargs), null, |
1151 if (invocationMoreSpecific(env, site, m22, mtype1.getParameterTypes(), allowBoxing, useVarargs)) { |
1360 allowBoxing, useVarargs, new MostSpecificCheck(!allowBoxing, actuals), noteWarner); |
1152 return true; |
1361 return mst != null && |
1153 } |
1362 !noteWarner.hasLint(Lint.LintCategory.UNCHECKED); |
1154 |
1363 } |
1155 //perform structural check |
1364 private List<Type> adjustArgs(List<Type> args, Symbol msym, int length, boolean allowVarargs) { |
1156 |
1365 if ((msym.flags() & VARARGS) != 0 && allowVarargs) { |
1157 List<Type> formals1 = mtype1.getParameterTypes(); |
1366 Type varargsElem = types.elemtype(args.last()); |
1158 Type lastFormal1 = formals1.last(); |
1367 if (varargsElem == null) { |
1159 List<Type> formals2 = mtype2.getParameterTypes(); |
1368 Assert.error("Bad varargs = " + args.last() + " " + msym); |
1160 Type lastFormal2 = formals2.last(); |
1369 } |
1161 ListBuffer<Type> newFormals = ListBuffer.lb(); |
1370 List<Type> newArgs = args.reverse().tail.prepend(varargsElem).reverse(); |
1162 |
1371 while (newArgs.length() < length) { |
1163 boolean hasStructuralPoly = false; |
1372 newArgs = newArgs.append(newArgs.last()); |
1164 for (Type actual : actuals) { |
1373 } |
1165 //perform formal argument adaptation in case actuals > formals (varargs) |
1374 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 { |
1375 } else { |
1262 return to; |
1376 return args; |
1263 } |
1377 } |
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 } |
1378 } |
1291 //where |
1379 //where |
1292 Type mostSpecificReturnType(Type mt1, Type mt2) { |
1380 Type mostSpecificReturnType(Type mt1, Type mt2) { |
1293 Type rt1 = mt1.getReturnType(); |
1381 Type rt1 = mt1.getReturnType(); |
1294 Type rt2 = mt2.getReturnType(); |
1382 Type rt2 = mt2.getReturnType(); |
2384 Type site, |
2472 Type site, |
2385 Name name, List<Type> argtypes, |
2473 Name name, List<Type> argtypes, |
2386 List<Type> typeargtypes, |
2474 List<Type> typeargtypes, |
2387 boolean boxingAllowed) { |
2475 boolean boxingAllowed) { |
2388 MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC; |
2476 MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC; |
|
2477 |
|
2478 ReferenceLookupHelper boundLookupHelper; |
|
2479 if (!name.equals(names.init)) { |
|
2480 //method reference |
|
2481 boundLookupHelper = |
|
2482 new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase); |
|
2483 } else if (site.hasTag(ARRAY)) { |
|
2484 //array constructor reference |
|
2485 boundLookupHelper = |
|
2486 new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); |
|
2487 } else { |
|
2488 //class constructor reference |
|
2489 boundLookupHelper = |
|
2490 new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase); |
|
2491 } |
|
2492 |
2389 //step 1 - bound lookup |
2493 //step 1 - bound lookup |
2390 ReferenceLookupHelper boundLookupHelper = name.equals(names.init) ? |
|
2391 new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase) : |
|
2392 new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase); |
|
2393 Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup()); |
2494 Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup()); |
2394 Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, boundLookupHelper); |
2495 Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, boundLookupHelper); |
2395 |
2496 |
2396 //step 2 - unbound lookup |
2497 //step 2 - unbound lookup |
2397 ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup(); |
2498 ReferenceLookupHelper unboundLookupHelper = boundLookupHelper.unboundLookup(); |
2621 } |
2722 } |
2622 |
2723 |
2623 @Override |
2724 @Override |
2624 ReferenceKind referenceKind(Symbol sym) { |
2725 ReferenceKind referenceKind(Symbol sym) { |
2625 return ReferenceKind.UNBOUND; |
2726 return ReferenceKind.UNBOUND; |
|
2727 } |
|
2728 } |
|
2729 |
|
2730 /** |
|
2731 * Helper class for array constructor lookup; an array constructor lookup |
|
2732 * is simulated by looking up a method that returns the array type specified |
|
2733 * as qualifier, and that accepts a single int parameter (size of the array). |
|
2734 */ |
|
2735 class ArrayConstructorReferenceLookupHelper extends ReferenceLookupHelper { |
|
2736 |
|
2737 ArrayConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List<Type> argtypes, |
|
2738 List<Type> typeargtypes, MethodResolutionPhase maxPhase) { |
|
2739 super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase); |
|
2740 } |
|
2741 |
|
2742 @Override |
|
2743 protected Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) { |
|
2744 Scope sc = new Scope(syms.arrayClass); |
|
2745 MethodSymbol arrayConstr = new MethodSymbol(PUBLIC, name, null, site.tsym); |
|
2746 arrayConstr.type = new MethodType(List.of(syms.intType), site, List.<Type>nil(), syms.methodClass); |
|
2747 sc.enter(arrayConstr); |
|
2748 return findMethodInScope(env, site, name, argtypes, typeargtypes, sc, methodNotFound, phase.isBoxingRequired(), phase.isVarargsRequired(), false, false); |
|
2749 } |
|
2750 |
|
2751 @Override |
|
2752 ReferenceKind referenceKind(Symbol sym) { |
|
2753 return ReferenceKind.ARRAY_CTOR; |
2626 } |
2754 } |
2627 } |
2755 } |
2628 |
2756 |
2629 /** |
2757 /** |
2630 * Helper class for constructor reference lookup. The lookup logic is based |
2758 * Helper class for constructor reference lookup. The lookup logic is based |