Fri, 24 Oct 2008 12:46:07 +0100
6746184: javac fails to compile call to public varargs method
Summary: javac's resolution process should go through all steps described in JLS 15.12.2.2
Reviewed-by: jjg
src/share/classes/com/sun/tools/javac/comp/Resolve.java | file | annotate | diff | comparison | revisions | |
test/tools/javac/varargs/T6746184.java | file | annotate | diff | comparison | revisions |
1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Oct 24 12:45:47 2008 +0100 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Oct 24 12:46:07 2008 +0100 1.3 @@ -30,6 +30,7 @@ 1.4 import com.sun.tools.javac.code.*; 1.5 import com.sun.tools.javac.jvm.*; 1.6 import com.sun.tools.javac.tree.*; 1.7 +import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*; 1.8 1.9 import com.sun.tools.javac.code.Type.*; 1.10 import com.sun.tools.javac.code.Symbol.*; 1.11 @@ -40,6 +41,9 @@ 1.12 import static com.sun.tools.javac.code.TypeTags.*; 1.13 import javax.lang.model.element.ElementVisitor; 1.14 1.15 +import java.util.Map; 1.16 +import java.util.HashMap; 1.17 + 1.18 /** Helper class for name resolution, used mostly by the attribution phase. 1.19 * 1.20 * <p><b>This is NOT part of any API supported by Sun Microsystems. If 1.21 @@ -1192,15 +1196,23 @@ 1.22 Name name, 1.23 List<Type> argtypes, 1.24 List<Type> typeargtypes) { 1.25 - Symbol sym = findFun(env, name, argtypes, typeargtypes, false, env.info.varArgs=false); 1.26 - if (varargsEnabled && sym.kind >= WRONG_MTHS) { 1.27 - sym = findFun(env, name, argtypes, typeargtypes, true, false); 1.28 - if (sym.kind >= WRONG_MTHS) 1.29 - sym = findFun(env, name, argtypes, typeargtypes, true, env.info.varArgs=true); 1.30 + Symbol sym = methodNotFound; 1.31 + List<MethodResolutionPhase> steps = methodResolutionSteps; 1.32 + while (steps.nonEmpty() && 1.33 + steps.head.isApplicable(boxingEnabled, varargsEnabled) && 1.34 + sym.kind >= ERRONEOUS) { 1.35 + sym = findFun(env, name, argtypes, typeargtypes, 1.36 + steps.head.isBoxingRequired, 1.37 + env.info.varArgs = steps.head.isVarargsRequired); 1.38 + methodResolutionCache.put(steps.head, sym); 1.39 + steps = steps.tail; 1.40 } 1.41 - if (sym.kind >= AMBIGUOUS) { 1.42 - sym = access( 1.43 - sym, pos, env.enclClass.sym.type, name, false, argtypes, typeargtypes); 1.44 + if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error 1.45 + MethodResolutionPhase errPhase = 1.46 + firstErroneousResolutionPhase(); 1.47 + sym = access(methodResolutionCache.get(errPhase), 1.48 + pos, env.enclClass.sym.type, name, false, argtypes, typeargtypes); 1.49 + env.info.varArgs = errPhase.isVarargsRequired; 1.50 } 1.51 return sym; 1.52 } 1.53 @@ -1217,17 +1229,23 @@ 1.54 Symbol resolveQualifiedMethod(DiagnosticPosition pos, Env<AttrContext> env, 1.55 Type site, Name name, List<Type> argtypes, 1.56 List<Type> typeargtypes) { 1.57 - Symbol sym = findMethod(env, site, name, argtypes, typeargtypes, false, 1.58 - env.info.varArgs=false, false); 1.59 - if (varargsEnabled && sym.kind >= WRONG_MTHS) { 1.60 - sym = findMethod(env, site, name, argtypes, typeargtypes, true, 1.61 - false, false); 1.62 - if (sym.kind >= WRONG_MTHS) 1.63 - sym = findMethod(env, site, name, argtypes, typeargtypes, true, 1.64 - env.info.varArgs=true, false); 1.65 + Symbol sym = methodNotFound; 1.66 + List<MethodResolutionPhase> steps = methodResolutionSteps; 1.67 + while (steps.nonEmpty() && 1.68 + steps.head.isApplicable(boxingEnabled, varargsEnabled) && 1.69 + sym.kind >= ERRONEOUS) { 1.70 + sym = findMethod(env, site, name, argtypes, typeargtypes, 1.71 + steps.head.isBoxingRequired(), 1.72 + env.info.varArgs = steps.head.isVarargsRequired(), false); 1.73 + methodResolutionCache.put(steps.head, sym); 1.74 + steps = steps.tail; 1.75 } 1.76 - if (sym.kind >= AMBIGUOUS) { 1.77 - sym = access(sym, pos, site, name, true, argtypes, typeargtypes); 1.78 + if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error 1.79 + MethodResolutionPhase errPhase = 1.80 + firstErroneousResolutionPhase(); 1.81 + sym = access(methodResolutionCache.get(errPhase), 1.82 + pos, site, name, true, argtypes, typeargtypes); 1.83 + env.info.varArgs = errPhase.isVarargsRequired; 1.84 } 1.85 return sym; 1.86 } 1.87 @@ -1268,14 +1286,22 @@ 1.88 Type site, 1.89 List<Type> argtypes, 1.90 List<Type> typeargtypes) { 1.91 - Symbol sym = resolveConstructor(pos, env, site, argtypes, typeargtypes, false, env.info.varArgs=false); 1.92 - if (varargsEnabled && sym.kind >= WRONG_MTHS) { 1.93 - sym = resolveConstructor(pos, env, site, argtypes, typeargtypes, true, false); 1.94 - if (sym.kind >= WRONG_MTHS) 1.95 - sym = resolveConstructor(pos, env, site, argtypes, typeargtypes, true, env.info.varArgs=true); 1.96 + Symbol sym = methodNotFound; 1.97 + List<MethodResolutionPhase> steps = methodResolutionSteps; 1.98 + while (steps.nonEmpty() && 1.99 + steps.head.isApplicable(boxingEnabled, varargsEnabled) && 1.100 + sym.kind >= ERRONEOUS) { 1.101 + sym = resolveConstructor(pos, env, site, argtypes, typeargtypes, 1.102 + steps.head.isBoxingRequired(), 1.103 + env.info.varArgs = steps.head.isVarargsRequired()); 1.104 + methodResolutionCache.put(steps.head, sym); 1.105 + steps = steps.tail; 1.106 } 1.107 - if (sym.kind >= AMBIGUOUS) { 1.108 - sym = access(sym, pos, site, names.init, true, argtypes, typeargtypes); 1.109 + if (sym.kind >= AMBIGUOUS) {//if nothing is found return the 'first' error 1.110 + MethodResolutionPhase errPhase = firstErroneousResolutionPhase(); 1.111 + sym = access(methodResolutionCache.get(errPhase), 1.112 + pos, site, names.init, true, argtypes, typeargtypes); 1.113 + env.info.varArgs = errPhase.isVarargsRequired(); 1.114 } 1.115 return sym; 1.116 } 1.117 @@ -1733,4 +1759,50 @@ 1.118 pair.sym2.location(site, types)); 1.119 } 1.120 } 1.121 + 1.122 + enum MethodResolutionPhase { 1.123 + BASIC(false, false), 1.124 + BOX(true, false), 1.125 + VARARITY(true, true); 1.126 + 1.127 + boolean isBoxingRequired; 1.128 + boolean isVarargsRequired; 1.129 + 1.130 + MethodResolutionPhase(boolean isBoxingRequired, boolean isVarargsRequired) { 1.131 + this.isBoxingRequired = isBoxingRequired; 1.132 + this.isVarargsRequired = isVarargsRequired; 1.133 + } 1.134 + 1.135 + public boolean isBoxingRequired() { 1.136 + return isBoxingRequired; 1.137 + } 1.138 + 1.139 + public boolean isVarargsRequired() { 1.140 + return isVarargsRequired; 1.141 + } 1.142 + 1.143 + public boolean isApplicable(boolean boxingEnabled, boolean varargsEnabled) { 1.144 + return (varargsEnabled || !isVarargsRequired) && 1.145 + (boxingEnabled || !isBoxingRequired); 1.146 + } 1.147 + } 1.148 + 1.149 + private Map<MethodResolutionPhase, Symbol> methodResolutionCache = 1.150 + new HashMap<MethodResolutionPhase, Symbol>(MethodResolutionPhase.values().length); 1.151 + 1.152 + final List<MethodResolutionPhase> methodResolutionSteps = List.of(BASIC, BOX, VARARITY); 1.153 + 1.154 + private MethodResolutionPhase firstErroneousResolutionPhase() { 1.155 + MethodResolutionPhase bestSoFar = BASIC; 1.156 + Symbol sym = methodNotFound; 1.157 + List<MethodResolutionPhase> steps = methodResolutionSteps; 1.158 + while (steps.nonEmpty() && 1.159 + steps.head.isApplicable(boxingEnabled, varargsEnabled) && 1.160 + sym.kind >= WRONG_MTHS) { 1.161 + sym = methodResolutionCache.get(steps.head); 1.162 + bestSoFar = steps.head; 1.163 + steps = steps.tail; 1.164 + } 1.165 + return bestSoFar; 1.166 + } 1.167 }
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/test/tools/javac/varargs/T6746184.java Fri Oct 24 12:46:07 2008 +0100 2.3 @@ -0,0 +1,39 @@ 2.4 +/* 2.5 + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. 2.11 + * 2.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.15 + * version 2 for more details (a copy is included in the LICENSE file that 2.16 + * accompanied this code). 2.17 + * 2.18 + * You should have received a copy of the GNU General Public License version 2.19 + * 2 along with this work; if not, write to the Free Software Foundation, 2.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.21 + * 2.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 2.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 2.24 + * have any questions. 2.25 + */ 2.26 + 2.27 +/* 2.28 + * @test 2.29 + * @bug 6746184 2.30 + * @summary javac fails to compile call to public varargs method 2.31 + */ 2.32 + 2.33 +public class T6746184 { 2.34 + public static void main(String[] args) { 2.35 + A.m(new Object()); 2.36 + } 2.37 +} 2.38 + 2.39 +class A { 2.40 + public static void m(final Object... varargs) {} 2.41 + private static void m(final Object singleArg) {} 2.42 +} 2.43 \ No newline at end of file