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

changeset 1570
f91144b7da75
parent 1521
71f35e4b93a5
child 1550
1df20330f6bd
equal deleted inserted replaced
1569:475eb15dfdad 1570:f91144b7da75
1 /* 1 /*
2 * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this 7 * published by the Free Software Foundation. Oracle designates this
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
52 import java.util.EnumSet; 53 import java.util.EnumSet;
53 import java.util.Iterator; 54 import java.util.Iterator;
54 import java.util.LinkedHashMap; 55 import java.util.LinkedHashMap;
55 import java.util.LinkedHashSet; 56 import java.util.LinkedHashSet;
56 import java.util.Map; 57 import java.util.Map;
57 import java.util.Set;
58 58
59 import javax.lang.model.element.ElementVisitor; 59 import javax.lang.model.element.ElementVisitor;
60 60
61 import static com.sun.tools.javac.code.Flags.*; 61 import static com.sun.tools.javac.code.Flags.*;
62 import static com.sun.tools.javac.code.Flags.BLOCK; 62 import static com.sun.tools.javac.code.Flags.BLOCK;
90 JCDiagnostic.Factory diags; 90 JCDiagnostic.Factory diags;
91 public final boolean boxingEnabled; // = source.allowBoxing(); 91 public final boolean boxingEnabled; // = source.allowBoxing();
92 public final boolean varargsEnabled; // = source.allowVarargs(); 92 public final boolean varargsEnabled; // = source.allowVarargs();
93 public final boolean allowMethodHandles; 93 public final boolean allowMethodHandles;
94 public final boolean allowDefaultMethods; 94 public final boolean allowDefaultMethods;
95 public final boolean allowStructuralMostSpecific;
95 private final boolean debugResolve; 96 private final boolean debugResolve;
96 final EnumSet<VerboseResolutionMode> verboseResolutionMode; 97 final EnumSet<VerboseResolutionMode> verboseResolutionMode;
97 98
98 Scope polymorphicSignatureScope; 99 Scope polymorphicSignatureScope;
99 100
125 debugResolve = options.isSet("debugresolve"); 126 debugResolve = options.isSet("debugresolve");
126 verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options); 127 verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options);
127 Target target = Target.instance(context); 128 Target target = Target.instance(context);
128 allowMethodHandles = target.hasMethodHandles(); 129 allowMethodHandles = target.hasMethodHandles();
129 allowDefaultMethods = source.allowDefaultMethods(); 130 allowDefaultMethods = source.allowDefaultMethods();
131 allowStructuralMostSpecific = source.allowStructuralMostSpecific();
130 polymorphicSignatureScope = new Scope(syms.noSymbol); 132 polymorphicSignatureScope = new Scope(syms.noSymbol);
131 133
132 inapplicableMethodException = new InapplicableMethodException(diags); 134 inapplicableMethodException = new InapplicableMethodException(diags);
133 } 135 }
134 136
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)
719 //check varargs element type accessibility 721 //check varargs element type accessibility
720 varargsAccessible(env, elt, inferenceContext); 722 varargsAccessible(env, elt, inferenceContext);
721 } 723 }
722 } 724 }
723 725
724 private void report(MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) { 726 private void reportMC(MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) {
725 boolean inferDiag = inferenceContext != infer.emptyContext; 727 boolean inferDiag = inferenceContext != infer.emptyContext;
726 InapplicableMethodException ex = inferDiag ? 728 InapplicableMethodException ex = inferDiag ?
727 infer.inferenceException : inapplicableMethodException; 729 infer.inferenceException : inapplicableMethodException;
728 if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) { 730 if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) {
729 Object[] args2 = new Object[args.length + 1]; 731 Object[] args2 = new Object[args.length + 1];
743 } 745 }
744 }); 746 });
745 } else { 747 } else {
746 if (!isAccessible(env, t)) { 748 if (!isAccessible(env, t)) {
747 Symbol location = env.enclClass.sym; 749 Symbol location = env.enclClass.sym;
748 report(MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location); 750 reportMC(MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location);
749 } 751 }
750 } 752 }
751 } 753 }
752 754
753 private ResultInfo methodCheckResult(final boolean varargsCheck, Type to, 755 private ResultInfo methodCheckResult(final boolean varargsCheck, Type to,
756 MethodCheckDiag methodDiag = varargsCheck ? 758 MethodCheckDiag methodDiag = varargsCheck ?
757 MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH; 759 MethodCheckDiag.VARARG_MISMATCH : MethodCheckDiag.ARG_MISMATCH;
758 760
759 @Override 761 @Override
760 public void report(DiagnosticPosition pos, JCDiagnostic details) { 762 public void report(DiagnosticPosition pos, JCDiagnostic details) {
761 report(methodDiag, deferredAttrContext.inferenceContext, details); 763 reportMC(methodDiag, deferredAttrContext.inferenceContext, details);
762 } 764 }
763 }; 765 };
764 return new MethodResultInfo(to, checkContext); 766 return new MethodResultInfo(to, checkContext);
765 } 767 }
766 }; 768 };
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
3379 return res; 3507 return res;
3380 } 3508 }
3381 3509
3382 @Override 3510 @Override
3383 protected Symbol access(Name name, TypeSymbol location) { 3511 protected Symbol access(Name name, TypeSymbol location) {
3384 return ambiguousSyms.last(); 3512 Symbol firstAmbiguity = ambiguousSyms.last();
3513 return firstAmbiguity.kind == TYP ?
3514 types.createErrorType(name, location, firstAmbiguity.type).tsym :
3515 firstAmbiguity;
3385 } 3516 }
3386 } 3517 }
3387 3518
3388 enum MethodResolutionPhase { 3519 enum MethodResolutionPhase {
3389 BASIC(false, false), 3520 BASIC(false, false),

mercurial