1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Oct 04 13:04:53 2012 +0100 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Oct 05 14:35:24 2012 +0100 1.3 @@ -753,6 +753,10 @@ 1.4 public boolean compatible(Type found, Type req, Warner warn) { 1.5 return types.isSubtypeUnchecked(found, inferenceContext.asFree(req, types), warn); 1.6 } 1.7 + 1.8 + public boolean allowBoxing() { 1.9 + return false; 1.10 + } 1.11 } 1.12 1.13 /** 1.14 @@ -769,6 +773,10 @@ 1.15 public boolean compatible(Type found, Type req, Warner warn) { 1.16 return types.isConvertible(found, inferenceContext.asFree(req, types), warn); 1.17 } 1.18 + 1.19 + public boolean allowBoxing() { 1.20 + return true; 1.21 + } 1.22 } 1.23 1.24 /** 1.25 @@ -1036,7 +1044,7 @@ 1.26 } 1.27 return (bestSoFar.kind > AMBIGUOUS) 1.28 ? sym 1.29 - : mostSpecific(sym, bestSoFar, env, site, 1.30 + : mostSpecific(argtypes, sym, bestSoFar, env, site, 1.31 allowBoxing && operator, useVarargs); 1.32 } 1.33 1.34 @@ -1050,7 +1058,7 @@ 1.35 * @param allowBoxing Allow boxing conversions of arguments. 1.36 * @param useVarargs Box trailing arguments into an array for varargs. 1.37 */ 1.38 - Symbol mostSpecific(Symbol m1, 1.39 + Symbol mostSpecific(List<Type> argtypes, Symbol m1, 1.40 Symbol m2, 1.41 Env<AttrContext> env, 1.42 final Type site, 1.43 @@ -1059,8 +1067,10 @@ 1.44 switch (m2.kind) { 1.45 case MTH: 1.46 if (m1 == m2) return m1; 1.47 - boolean m1SignatureMoreSpecific = signatureMoreSpecific(env, site, m1, m2, allowBoxing, useVarargs); 1.48 - boolean m2SignatureMoreSpecific = signatureMoreSpecific(env, site, m2, m1, allowBoxing, useVarargs); 1.49 + boolean m1SignatureMoreSpecific = 1.50 + signatureMoreSpecific(argtypes, env, site, m1, m2, allowBoxing, useVarargs); 1.51 + boolean m2SignatureMoreSpecific = 1.52 + signatureMoreSpecific(argtypes, env, site, m2, m1, allowBoxing, useVarargs); 1.53 if (m1SignatureMoreSpecific && m2SignatureMoreSpecific) { 1.54 Type mt1 = types.memberType(site, m1); 1.55 Type mt2 = types.memberType(site, m2); 1.56 @@ -1127,8 +1137,8 @@ 1.57 return ambiguityError(m1, m2); 1.58 case AMBIGUOUS: 1.59 AmbiguityError e = (AmbiguityError)m2; 1.60 - Symbol err1 = mostSpecific(m1, e.sym, env, site, allowBoxing, useVarargs); 1.61 - Symbol err2 = mostSpecific(m1, e.sym2, env, site, allowBoxing, useVarargs); 1.62 + Symbol err1 = mostSpecific(argtypes, m1, e.sym, env, site, allowBoxing, useVarargs); 1.63 + Symbol err2 = mostSpecific(argtypes, m1, e.sym2, env, site, allowBoxing, useVarargs); 1.64 if (err1 == err2) return err1; 1.65 if (err1 == e.sym && err2 == e.sym2) return m2; 1.66 if (err1 instanceof AmbiguityError && 1.67 @@ -1142,13 +1152,82 @@ 1.68 } 1.69 } 1.70 //where 1.71 - private boolean signatureMoreSpecific(Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean allowBoxing, boolean useVarargs) { 1.72 + private boolean signatureMoreSpecific(List<Type> actuals, Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean allowBoxing, boolean useVarargs) { 1.73 + Symbol m12 = adjustVarargs(m1, m2, useVarargs); 1.74 + Symbol m22 = adjustVarargs(m2, m1, useVarargs); 1.75 + Type mtype1 = types.memberType(site, m12); 1.76 + Type mtype2 = types.memberType(site, m22); 1.77 + 1.78 + //check if invocation is more specific 1.79 + if (invocationMoreSpecific(env, site, m22, mtype1.getParameterTypes(), allowBoxing, useVarargs)) { 1.80 + return true; 1.81 + } 1.82 + 1.83 + //perform structural check 1.84 + 1.85 + List<Type> formals1 = mtype1.getParameterTypes(); 1.86 + Type lastFormal1 = formals1.last(); 1.87 + List<Type> formals2 = mtype2.getParameterTypes(); 1.88 + Type lastFormal2 = formals2.last(); 1.89 + ListBuffer<Type> newFormals = ListBuffer.lb(); 1.90 + 1.91 + boolean hasStructuralPoly = false; 1.92 + for (Type actual : actuals) { 1.93 + //perform formal argument adaptation in case actuals > formals (varargs) 1.94 + Type f1 = formals1.isEmpty() ? 1.95 + lastFormal1 : formals1.head; 1.96 + Type f2 = formals2.isEmpty() ? 1.97 + lastFormal2 : formals2.head; 1.98 + 1.99 + //is this a structural actual argument? 1.100 + boolean isStructuralPoly = actual.tag == DEFERRED && 1.101 + ((DeferredType)actual).tree.hasTag(LAMBDA); 1.102 + 1.103 + Type newFormal = f1; 1.104 + 1.105 + if (isStructuralPoly) { 1.106 + //for structural arguments only - check that corresponding formals 1.107 + //are related - if so replace formal with <null> 1.108 + hasStructuralPoly = true; 1.109 + DeferredType dt = (DeferredType)actual; 1.110 + Type t1 = deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, m1, currentResolutionContext.step).apply(dt); 1.111 + Type t2 = deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, m2, currentResolutionContext.step).apply(dt); 1.112 + if (t1.isErroneous() || t2.isErroneous() || !isStructuralSubtype(t1, t2)) { 1.113 + //not structural subtypes - simply fail 1.114 + return false; 1.115 + } else { 1.116 + newFormal = syms.botType; 1.117 + } 1.118 + } 1.119 + 1.120 + newFormals.append(newFormal); 1.121 + if (newFormals.length() > mtype2.getParameterTypes().length()) { 1.122 + //expand m2's type so as to fit the new formal arity (varargs) 1.123 + m22.type = types.createMethodTypeWithParameters(m22.type, m22.type.getParameterTypes().append(f2)); 1.124 + } 1.125 + 1.126 + formals1 = formals1.isEmpty() ? formals1 : formals1.tail; 1.127 + formals2 = formals2.isEmpty() ? formals2 : formals2.tail; 1.128 + } 1.129 + 1.130 + if (!hasStructuralPoly) { 1.131 + //if no structural actual was found, we're done 1.132 + return false; 1.133 + } 1.134 + //perform additional adaptation if actuals < formals (varargs) 1.135 + for (Type t : formals1) { 1.136 + newFormals.append(t); 1.137 + } 1.138 + //check if invocation (with tweaked args) is more specific 1.139 + return invocationMoreSpecific(env, site, m22, newFormals.toList(), allowBoxing, useVarargs); 1.140 + } 1.141 + //where 1.142 + private boolean invocationMoreSpecific(Env<AttrContext> env, Type site, Symbol m2, List<Type> argtypes1, boolean allowBoxing, boolean useVarargs) { 1.143 noteWarner.clear(); 1.144 - Type mtype1 = types.memberType(site, adjustVarargs(m1, m2, useVarargs)); 1.145 - Type mtype2 = instantiate(env, site, adjustVarargs(m2, m1, useVarargs), null, 1.146 - types.lowerBoundArgtypes(mtype1), null, 1.147 + Type mst = instantiate(env, site, m2, null, 1.148 + types.lowerBounds(argtypes1), null, 1.149 allowBoxing, false, noteWarner); 1.150 - return mtype2 != null && 1.151 + return mst != null && 1.152 !noteWarner.hasLint(Lint.LintCategory.UNCHECKED); 1.153 } 1.154 //where 1.155 @@ -1187,6 +1266,32 @@ 1.156 } 1.157 } 1.158 //where 1.159 + boolean isStructuralSubtype(Type s, Type t) { 1.160 + 1.161 + Type ret_s = types.findDescriptorType(s).getReturnType(); 1.162 + Type ret_t = types.findDescriptorType(t).getReturnType(); 1.163 + 1.164 + //covariant most specific check for function descriptor return type 1.165 + if (!types.isSubtype(ret_s, ret_t)) { 1.166 + return false; 1.167 + } 1.168 + 1.169 + List<Type> args_s = types.findDescriptorType(s).getParameterTypes(); 1.170 + List<Type> args_t = types.findDescriptorType(t).getParameterTypes(); 1.171 + 1.172 + //arity must be identical 1.173 + if (args_s.length() != args_t.length()) { 1.174 + return false; 1.175 + } 1.176 + 1.177 + //invariant most specific check for function descriptor parameter types 1.178 + if (!types.isSameTypes(args_t, args_s)) { 1.179 + return false; 1.180 + } 1.181 + 1.182 + return true; 1.183 + } 1.184 + //where 1.185 Type mostSpecificReturnType(Type mt1, Type mt2) { 1.186 Type rt1 = mt1.getReturnType(); 1.187 Type rt2 = mt2.getReturnType(); 1.188 @@ -2388,7 +2493,19 @@ 1.189 private final LocalizedString noArgs = new LocalizedString("compiler.misc.no.args"); 1.190 1.191 public Object methodArguments(List<Type> argtypes) { 1.192 - return argtypes == null || argtypes.isEmpty() ? noArgs : argtypes; 1.193 + if (argtypes == null || argtypes.isEmpty()) { 1.194 + return noArgs; 1.195 + } else { 1.196 + ListBuffer<Object> diagArgs = ListBuffer.lb(); 1.197 + for (Type t : argtypes) { 1.198 + if (t.tag == DEFERRED) { 1.199 + diagArgs.append(((DeferredAttr.DeferredType)t).tree); 1.200 + } else { 1.201 + diagArgs.append(t); 1.202 + } 1.203 + } 1.204 + return diagArgs; 1.205 + } 1.206 } 1.207 1.208 /**