# HG changeset patch # User mcimadamore # Date 1315919739 -3600 # Node ID dca7012223bcb8af3f86da7d78a13f32f9196319 # Parent d8e900b62e0276a7ea7bddc37032bb38256011d1 7086601: Error message bug: cause for method mismatch is 'null' Summary: Inference error during lub() does not set 'cause' for method resolution diagnostic Reviewed-by: jjg diff -r d8e900b62e02 -r dca7012223bc langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Tue Sep 13 14:15:22 2011 +0100 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Tue Sep 13 14:15:39 2011 +0100 @@ -269,21 +269,18 @@ // VGJ: sort of inlined maximizeInst() below. Adding // bounds can cause lobounds that are above hibounds. List hibounds = Type.filter(that.hibounds, errorFilter); + Type hb = null; if (hibounds.isEmpty()) - return; - Type hb = null; - if (hibounds.tail.isEmpty()) + hb = syms.objectType; + else if (hibounds.tail.isEmpty()) hb = hibounds.head; - else for (List bs = hibounds; - bs.nonEmpty() && hb == null; - bs = bs.tail) { - if (isSubClass(bs.head, hibounds)) - hb = types.fromUnknownFun.apply(bs.head); - } + else + hb = types.glb(hibounds); if (hb == null || - !types.isSubtypeUnchecked(hb, hibounds, warn) || - !types.isSubtypeUnchecked(that.inst, hb, warn)) - throw ambiguousNoInstanceException; + hb.isErroneous()) + throw ambiguousNoInstanceException + .setMessage("incompatible.upper.bounds", + that.qtype, hibounds); } } diff -r d8e900b62e02 -r dca7012223bc langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Sep 13 14:15:22 2011 +0100 +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Sep 13 14:15:39 2011 +0100 @@ -1602,6 +1602,10 @@ compiler.misc.no.unique.minimal.instance.exists=\ no unique minimal instance exists for type variable {0} with lower bounds {1} +# 0: type, 1: list of type +compiler.misc.incompatible.upper.bounds=\ + inference variable {0} has incompatible upper bounds {1} + # 0: list of type, 1: type, 2: type compiler.misc.infer.no.conforming.instance.exists=\ no instance(s) of type variable(s) {0} exist so that {1} conforms to {2} diff -r d8e900b62e02 -r dca7012223bc langtools/test/tools/javac/diags/examples/IncompatibleUpperBounds.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/diags/examples/IncompatibleUpperBounds.java Tue Sep 13 14:15:39 2011 +0100 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +//key: compiler.err.cant.apply.symbols +//key: compiler.misc.inapplicable.method +//key: compiler.misc.arg.length.mismatch +//key: compiler.misc.incompatible.upper.bounds + +import java.util.List; + +class IncompatibleUpperBounds { + void m(List s1, List s2) { } + void m(Object o) {} + + void test(List li, List ls) { + m(li, ls); + } +} diff -r d8e900b62e02 -r dca7012223bc langtools/test/tools/javac/generics/inference/7086601/T7086601a.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/generics/inference/7086601/T7086601a.java Tue Sep 13 14:15:39 2011 +0100 @@ -0,0 +1,34 @@ +/** + * @test /nodynamiccopyright/ + * @bug 7086601 + * @summary Error message bug: cause for method mismatch is 'null' + * @compile/fail/ref=T7086601a.out -XDrawDiagnostics T7086601a.java + */ + +class T7086601 { + static void m1(Iterable s1, Iterable s2) { } + static void m1(Object o) {} + + static void m2(Iterable s1, Iterable s2, Iterable s3) { } + static void m2(Object o) {} + + @SafeVarargs + static void m3(Iterable... ss) { } + static void m3(Object o) {} + + static void test1(Iterable is, Iterable ii) { + m1(is, ii); + } + + static void test2(Iterable is, Iterable ii, Iterable id) { + m2(is, ii, id); + } + + static void test3(Iterable is, Iterable ii) { + m3(is, ii); + } + + static void test4(Iterable is, Iterable ii, Iterable id) { + m3(is, ii, id); + } +} diff -r d8e900b62e02 -r dca7012223bc langtools/test/tools/javac/generics/inference/7086601/T7086601a.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/generics/inference/7086601/T7086601a.out Tue Sep 13 14:15:39 2011 +0100 @@ -0,0 +1,5 @@ +T7086601a.java:20:9: compiler.err.cant.apply.symbols: kindname.method, m1, java.lang.Iterable,java.lang.Iterable,{(compiler.misc.inapplicable.method: kindname.method, T7086601, m1(java.lang.Object), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, T7086601, m1(java.lang.Iterable,java.lang.Iterable), (compiler.misc.incompatible.upper.bounds: S, java.lang.Integer,java.lang.String))} +T7086601a.java:24:9: compiler.err.cant.apply.symbols: kindname.method, m2, java.lang.Iterable,java.lang.Iterable,java.lang.Iterable,{(compiler.misc.inapplicable.method: kindname.method, T7086601, m2(java.lang.Object), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, T7086601, m2(java.lang.Iterable,java.lang.Iterable,java.lang.Iterable), (compiler.misc.incompatible.upper.bounds: S, java.lang.Double,java.lang.Integer,java.lang.String))} +T7086601a.java:28:9: compiler.err.cant.apply.symbols: kindname.method, m3, java.lang.Iterable,java.lang.Iterable,{(compiler.misc.inapplicable.method: kindname.method, T7086601, m3(java.lang.Object), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, T7086601, m3(java.lang.Iterable...), (compiler.misc.incompatible.upper.bounds: S, java.lang.Integer,java.lang.String))} +T7086601a.java:32:9: compiler.err.cant.apply.symbols: kindname.method, m3, java.lang.Iterable,java.lang.Iterable,java.lang.Iterable,{(compiler.misc.inapplicable.method: kindname.method, T7086601, m3(java.lang.Object), (compiler.misc.arg.length.mismatch)),(compiler.misc.inapplicable.method: kindname.method, T7086601, m3(java.lang.Iterable...), (compiler.misc.incompatible.upper.bounds: S, java.lang.Double,java.lang.Integer,java.lang.String))} +4 errors diff -r d8e900b62e02 -r dca7012223bc langtools/test/tools/javac/generics/inference/7086601/T7086601b.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/generics/inference/7086601/T7086601b.java Tue Sep 13 14:15:39 2011 +0100 @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7086601 + * @summary Error message bug: cause for method mismatch is 'null' + */ + +import com.sun.source.util.JavacTask; +import java.net.URI; +import java.util.Arrays; +import java.util.ArrayList; +import javax.tools.Diagnostic; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + + +public class T7086601b { + + static int checkCount = 0; + + enum TypeKind { + STRING("String", false), + INTEGER("Integer", false), + NUMBER("Number", false), + SERIALIZABLE("java.io.Serializable", true), + CLONEABLE("Cloneable", true), + X("X", false), + Y("Y", false), + Z("Z", false); + + String typeStr; + boolean isInterface; + + private TypeKind(String typeStr, boolean isInterface) { + this.typeStr = typeStr; + this.isInterface = isInterface; + } + + boolean isSubtypeof(TypeKind other) { + return (this == INTEGER && other == NUMBER || + this == Z && other == Y || + this == other); + } + } + + enum MethodCallKind { + ARITY_ONE("m(a1);", 1), + ARITY_TWO("m(a1, a2);", 2), + ARITY_THREE("m(a1, a2, a3);", 3); + + String invokeString; + int arity; + + private MethodCallKind(String invokeString, int arity) { + this.invokeString = invokeString; + this.arity = arity; + } + } + + public static void main(String... args) throws Exception { + + //create default shared JavaCompiler - reused across multiple compilations + JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); + + for (TypeKind a1 : TypeKind.values()) { + for (TypeKind a2 : TypeKind.values()) { + for (TypeKind a3 : TypeKind.values()) { + for (MethodCallKind mck : MethodCallKind.values()) { + new T7086601b(a1, a2, a3, mck).run(comp, fm); + } + } + } + } + System.out.println("Total check executed: " + checkCount); + } + + TypeKind a1; + TypeKind a2; + TypeKind a3; + MethodCallKind mck; + JavaSource source; + DiagnosticChecker diagChecker; + + T7086601b(TypeKind a1, TypeKind a2, TypeKind a3, MethodCallKind mck) { + this.a1 = a1; + this.a2 = a2; + this.a3 = a3; + this.mck = mck; + this.source = new JavaSource(); + this.diagChecker = new DiagnosticChecker(); + } + + class JavaSource extends SimpleJavaFileObject { + + final String bodyTemplate = "import java.util.List;\n"+ + "class Test {\n" + + " void m(List l1) { }\n" + + " void m(List l1, List l2) { }\n" + + " void m(List l1, List l2, List l3) { }\n" + + " void test(List<#A1> a1, List<#A2> a2, List<#A3> a3) { #MC } }"; + + String source; + + public JavaSource() { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + source = bodyTemplate.replace("#A1", a1.typeStr) + .replace("#A2", a2.typeStr).replace("#A3", a3.typeStr) + .replace("#MC", mck.invokeString); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + } + + void run(JavaCompiler tool, StandardJavaFileManager fm) throws Exception { + JavacTask ct = (JavacTask)tool.getTask(null, fm, diagChecker, + null, null, Arrays.asList(source)); + try { + ct.analyze(); + } catch (Throwable ex) { + throw new AssertionError("Error thron when compiling the following code:\n" + source.getCharContent(true)); + } + check(); + } + + void check() { + checkCount++; + + boolean errorExpected = false; + + if (mck.arity > 1) { + TypeKind[] argtypes = { a1, a2, a3 }; + ArrayList classes = new ArrayList<>(); + for (int i = 0 ; i < mck.arity ; i ++ ) { + if (!argtypes[i].isInterface) { + classes.add(argtypes[i]); + } + } + boolean glb_exists = true; + for (TypeKind arg_i : classes) { + glb_exists = true; + for (TypeKind arg_j : classes) { + if (!arg_i.isSubtypeof(arg_j)) { + glb_exists = false; + break; + } + } + if (glb_exists) break; + } + errorExpected = !glb_exists; + } + + if (errorExpected != diagChecker.errorFound) { + throw new Error("invalid diagnostics for source:\n" + + source.getCharContent(true) + + "\nFound error: " + diagChecker.errorFound + + "\nExpected error: " + errorExpected); + } + } + + static class DiagnosticChecker implements javax.tools.DiagnosticListener { + + boolean errorFound; + + public void report(Diagnostic diagnostic) { + if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { + errorFound = true; + } + } + } +}