Thu, 25 Jul 2013 14:51:40 +0100
8020843: javac crashes on accessibility check with method reference with typevar receiver
Summary: method reference overload check doesn't walk through type-variable receivers
Reviewed-by: jjg
1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Jul 25 14:49:16 2013 +0100 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Jul 25 14:51:40 2013 +0100 1.3 @@ -2649,6 +2649,13 @@ 1.4 InferenceContext inferenceContext) { 1.5 MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC; 1.6 1.7 + if (site.hasTag(TYPEVAR)) { 1.8 + return resolveMemberReference(pos, env, referenceTree, site.getUpperBound(), 1.9 + name, argtypes, typeargtypes, boxingAllowed, methodCheck, inferenceContext); 1.10 + } 1.11 + 1.12 + site = types.capture(site); 1.13 + 1.14 ReferenceLookupHelper boundLookupHelper; 1.15 if (!name.equals(names.init)) { 1.16 //method reference 1.17 @@ -2675,24 +2682,52 @@ 1.18 1.19 //merge results 1.20 Pair<Symbol, ReferenceLookupHelper> res; 1.21 - if (!lookupSuccess(unboundSym)) { 1.22 - res = new Pair<Symbol, ReferenceLookupHelper>(boundSym, boundLookupHelper); 1.23 - env.info.pendingResolutionPhase = boundEnv.info.pendingResolutionPhase; 1.24 - } else if (lookupSuccess(boundSym)) { 1.25 - res = new Pair<Symbol, ReferenceLookupHelper>(ambiguityError(boundSym, unboundSym), boundLookupHelper); 1.26 - env.info.pendingResolutionPhase = boundEnv.info.pendingResolutionPhase; 1.27 - } else { 1.28 - res = new Pair<Symbol, ReferenceLookupHelper>(unboundSym, unboundLookupHelper); 1.29 - env.info.pendingResolutionPhase = unboundEnv.info.pendingResolutionPhase; 1.30 - } 1.31 + Symbol bestSym = choose(boundSym, unboundSym); 1.32 + res = new Pair<Symbol, ReferenceLookupHelper>(bestSym, 1.33 + bestSym == unboundSym ? unboundLookupHelper : boundLookupHelper); 1.34 + env.info.pendingResolutionPhase = bestSym == unboundSym ? 1.35 + unboundEnv.info.pendingResolutionPhase : 1.36 + boundEnv.info.pendingResolutionPhase; 1.37 1.38 return res; 1.39 } 1.40 - //private 1.41 - boolean lookupSuccess(Symbol s) { 1.42 + //where 1.43 + private Symbol choose(Symbol s1, Symbol s2) { 1.44 + if (lookupSuccess(s1) && lookupSuccess(s2)) { 1.45 + return ambiguityError(s1, s2); 1.46 + } else if (lookupSuccess(s1) || 1.47 + (canIgnore(s2) && !canIgnore(s1))) { 1.48 + return s1; 1.49 + } else if (lookupSuccess(s2) || 1.50 + (canIgnore(s1) && !canIgnore(s2))) { 1.51 + return s2; 1.52 + } else { 1.53 + return s1; 1.54 + } 1.55 + } 1.56 + 1.57 + private boolean lookupSuccess(Symbol s) { 1.58 return s.kind == MTH || s.kind == AMBIGUOUS; 1.59 } 1.60 1.61 + private boolean canIgnore(Symbol s) { 1.62 + switch (s.kind) { 1.63 + case ABSENT_MTH: 1.64 + return true; 1.65 + case WRONG_MTH: 1.66 + InapplicableSymbolError errSym = 1.67 + (InapplicableSymbolError)s; 1.68 + return new Template(MethodCheckDiag.ARITY_MISMATCH.regex()) 1.69 + .matches(errSym.errCandidate().snd); 1.70 + case WRONG_MTHS: 1.71 + InapplicableSymbolsError errSyms = 1.72 + (InapplicableSymbolsError)s; 1.73 + return errSyms.filterCandidates(errSyms.mapCandidates()).isEmpty(); 1.74 + default: 1.75 + return false; 1.76 + } 1.77 + } 1.78 + 1.79 /** 1.80 * Helper for defining custom method-like lookup logic; a lookup helper 1.81 * provides hooks for (i) the actual lookup logic and (ii) accessing the 1.82 @@ -3504,7 +3539,9 @@ 1.83 List<Type> argtypes, 1.84 List<Type> typeargtypes) { 1.85 Map<Symbol, JCDiagnostic> candidatesMap = mapCandidates(); 1.86 - Map<Symbol, JCDiagnostic> filteredCandidates = filterCandidates(candidatesMap); 1.87 + Map<Symbol, JCDiagnostic> filteredCandidates = compactMethodDiags ? 1.88 + filterCandidates(candidatesMap) : 1.89 + mapCandidates(); 1.90 if (filteredCandidates.isEmpty()) { 1.91 filteredCandidates = candidatesMap; 1.92 } 1.93 @@ -3556,8 +3593,7 @@ 1.94 Map<Symbol, JCDiagnostic> candidates = new LinkedHashMap<Symbol, JCDiagnostic>(); 1.95 for (Map.Entry<Symbol, JCDiagnostic> _entry : candidatesMap.entrySet()) { 1.96 JCDiagnostic d = _entry.getValue(); 1.97 - if (!compactMethodDiags || 1.98 - !new Template(MethodCheckDiag.ARITY_MISMATCH.regex()).matches(d)) { 1.99 + if (!new Template(MethodCheckDiag.ARITY_MISMATCH.regex()).matches(d)) { 1.100 candidates.put(_entry.getKey(), d); 1.101 } 1.102 }
2.1 --- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Jul 25 14:49:16 2013 +0100 2.2 +++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Jul 25 14:51:40 2013 +0100 2.3 @@ -905,6 +905,10 @@ 2.4 compiler.err.report.access=\ 2.5 {0} has {1} access in {2} 2.6 2.7 +# 0: symbol, 1: set of modifier, 2: symbol 2.8 +compiler.misc.report.access=\ 2.9 + {0} has {1} access in {2} 2.10 + 2.11 compiler.err.ret.outside.meth=\ 2.12 return outside method 2.13
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/tools/javac/diags/examples/ReportAccessFragment.java Thu Jul 25 14:51:40 2013 +0100 3.3 @@ -0,0 +1,32 @@ 3.4 +/* 3.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3.7 + * 3.8 + * This code is free software; you can redistribute it and/or modify it 3.9 + * under the terms of the GNU General Public License version 2 only, as 3.10 + * published by the Free Software Foundation. 3.11 + * 3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 3.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 3.15 + * version 2 for more details (a copy is included in the LICENSE file that 3.16 + * accompanied this code). 3.17 + * 3.18 + * You should have received a copy of the GNU General Public License version 3.19 + * 2 along with this work; if not, write to the Free Software Foundation, 3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 3.21 + * 3.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 3.23 + * or visit www.oracle.com if you need additional information or have any 3.24 + * questions. 3.25 + */ 3.26 + 3.27 +// key: compiler.err.prob.found.req 3.28 +// key: compiler.misc.invalid.mref 3.29 +// key: compiler.misc.report.access 3.30 + 3.31 +class ReportAccessFragment { 3.32 + void test(Object o) { 3.33 + Runnable r = o::clone; 3.34 + } 3.35 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/tools/javac/lambda/8020843/T8020843a.java Thu Jul 25 14:51:40 2013 +0100 4.3 @@ -0,0 +1,16 @@ 4.4 +/* 4.5 + * @test /nodynamiccopyright/ 4.6 + * @bug 8020843 4.7 + * @summary javac crashes on accessibility check with method reference with typevar receiver 4.8 + * @compile/fail/ref=T8020843a.out -XDrawDiagnostics T8020843a.java 4.9 + */ 4.10 + 4.11 +class T8020843a { 4.12 + interface Function<X, Y> { 4.13 + Y m(X x); 4.14 + } 4.15 + 4.16 + <T> void test(T t) { 4.17 + Function<T, Object> ss = T::clone; 4.18 + } 4.19 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/tools/javac/lambda/8020843/T8020843a.out Thu Jul 25 14:51:40 2013 +0100 5.3 @@ -0,0 +1,2 @@ 5.4 +T8020843a.java:14:34: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.report.access: clone(), protected, java.lang.Object)) 5.5 +1 error
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/tools/javac/lambda/8020843/T8020843b.java Thu Jul 25 14:51:40 2013 +0100 6.3 @@ -0,0 +1,27 @@ 6.4 +/* 6.5 + * @test /nodynamiccopyright/ 6.6 + * @bug 8020843 6.7 + * @summary javac crashes on accessibility check with method reference with typevar receiver 6.8 + * @compile/fail/ref=T8020843b.out -XDrawDiagnostics T8020843b.java 6.9 + */ 6.10 + 6.11 +class T8020843b { 6.12 + interface Function<X, Y> { 6.13 + Y m(X x); 6.14 + } 6.15 + 6.16 + interface BiFunction<X, Y, Z> { 6.17 + Z m(X x, Y y); 6.18 + } 6.19 + 6.20 + Object m(int i) { return null; } 6.21 + static Object m(String t) { return null; } 6.22 + 6.23 + Object m2(int i) { return null; } 6.24 + static Object m2(long t) { return null; } 6.25 + 6.26 + static void test() { 6.27 + Function<T8020843b, Object> f1 = T8020843b::m; //show bound case diag 6.28 + BiFunction<T8020843b, String, Object> f2 = T8020843b::m2; //show unbound case diag 6.29 + } 6.30 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/test/tools/javac/lambda/8020843/T8020843b.out Thu Jul 25 14:51:40 2013 +0100 7.3 @@ -0,0 +1,3 @@ 7.4 +T8020843b.java:24:42: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbols: kindname.method, m, T8020843b,{(compiler.misc.inapplicable.method: kindname.method, T8020843b, m(int), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: T8020843b, int))),(compiler.misc.inapplicable.method: kindname.method, T8020843b, m(java.lang.String), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: T8020843b, java.lang.String)))})) 7.5 +T8020843b.java:25:52: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbols: kindname.method, m2, T8020843b,java.lang.String,{(compiler.misc.inapplicable.method: kindname.method, T8020843b, m2(int), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, int))),(compiler.misc.inapplicable.method: kindname.method, T8020843b, m2(long), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.String, long)))})) 7.6 +2 errors
8.1 --- a/test/tools/javac/lambda/MethodReference28.out Thu Jul 25 14:49:16 2013 +0100 8.2 +++ b/test/tools/javac/lambda/MethodReference28.out Thu Jul 25 14:51:40 2013 +0100 8.3 @@ -9,6 +9,6 @@ 8.4 MethodReference28.java:46:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m3, java.lang.String, int, kindname.class, MethodReference28, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: int, java.lang.String)))) 8.5 MethodReference28.java:47:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m4, java.lang.String[], int, kindname.class, MethodReference28, (compiler.misc.varargs.argument.mismatch: (compiler.misc.inconvertible.types: int, java.lang.String)))) 8.6 MethodReference28.java:52:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m2, java.lang.Integer,java.lang.Integer, MethodReference28,int, kindname.class, MethodReference28, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: MethodReference28, java.lang.Integer)))) 8.7 -MethodReference28.java:53:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m3, java.lang.String, MethodReference28,int, kindname.class, MethodReference28, (compiler.misc.arg.length.mismatch))) 8.8 +MethodReference28.java:53:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m3, java.lang.String, MethodReference28,int, kindname.class, MethodReference28, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: int, java.lang.String)))) 8.9 MethodReference28.java:54:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m4, java.lang.String[], MethodReference28,int, kindname.class, MethodReference28, (compiler.misc.varargs.argument.mismatch: (compiler.misc.inconvertible.types: MethodReference28, java.lang.String)))) 8.10 13 errors