Mon, 24 Jan 2011 15:44:15 +0000
6943278: spurious error message for inference and type-variable with erroneous bound
Summary: type-inference should ignore erroneous bounds
Reviewed-by: jjg
1.1 --- a/src/share/classes/com/sun/tools/javac/code/Type.java Wed Jan 19 19:01:35 2011 -0800 1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Type.java Mon Jan 24 15:44:15 2011 +0000 1.3 @@ -365,6 +365,16 @@ 1.4 return false; 1.5 } 1.6 1.7 + public static List<Type> filter(List<Type> ts, Filter<Type> tf) { 1.8 + ListBuffer<Type> buf = ListBuffer.lb(); 1.9 + for (Type t : ts) { 1.10 + if (tf.accepts(t)) { 1.11 + buf.append(t); 1.12 + } 1.13 + } 1.14 + return buf.toList(); 1.15 + } 1.16 + 1.17 public boolean isSuperBound() { return false; } 1.18 public boolean isExtendsBound() { return false; } 1.19 public boolean isUnbound() { return false; }
2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Wed Jan 19 19:01:35 2011 -0800 2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Mon Jan 24 15:44:15 2011 +0000 2.3 @@ -800,7 +800,8 @@ 2.4 Type actual = types.subst(args.head, 2.5 type.tsym.type.getTypeArguments(), 2.6 tvars_buf.toList()); 2.7 - if (!checkExtends(actual, (TypeVar)tvars.head)) { 2.8 + if (!checkExtends(actual, (TypeVar)tvars.head) && 2.9 + !tvars.head.getUpperBound().isErroneous()) { 2.10 return args.head; 2.11 } 2.12 args = args.tail; 2.13 @@ -808,11 +809,15 @@ 2.14 } 2.15 2.16 args = type.getTypeArguments(); 2.17 + tvars = tvars_buf.toList(); 2.18 2.19 for (Type arg : types.capture(type).getTypeArguments()) { 2.20 - if (arg.tag == TYPEVAR && arg.getUpperBound().isErroneous()) { 2.21 + if (arg.tag == TYPEVAR && 2.22 + arg.getUpperBound().isErroneous() && 2.23 + !tvars.head.getUpperBound().isErroneous()) { 2.24 return args.head; 2.25 } 2.26 + tvars = tvars.tail; 2.27 } 2.28 2.29 return null;
3.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java Wed Jan 19 19:01:35 2011 -0800 3.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java Mon Jan 24 15:44:15 2011 +0000 3.3 @@ -205,19 +205,20 @@ 3.4 * Throw a NoInstanceException if this not possible. 3.5 */ 3.6 void maximizeInst(UndetVar that, Warner warn) throws NoInstanceException { 3.7 + List<Type> hibounds = Type.filter(that.hibounds, errorFilter); 3.8 if (that.inst == null) { 3.9 - if (that.hibounds.isEmpty()) 3.10 + if (hibounds.isEmpty()) 3.11 that.inst = syms.objectType; 3.12 - else if (that.hibounds.tail.isEmpty()) 3.13 - that.inst = that.hibounds.head; 3.14 + else if (hibounds.tail.isEmpty()) 3.15 + that.inst = hibounds.head; 3.16 else 3.17 - that.inst = types.glb(that.hibounds); 3.18 + that.inst = types.glb(hibounds); 3.19 } 3.20 if (that.inst == null || 3.21 that.inst.isErroneous()) 3.22 throw ambiguousNoInstanceException 3.23 .setMessage("no.unique.maximal.instance.exists", 3.24 - that.qtype, that.hibounds); 3.25 + that.qtype, hibounds); 3.26 } 3.27 //where 3.28 private boolean isSubClass(Type t, final List<Type> ts) { 3.29 @@ -241,37 +242,46 @@ 3.30 return true; 3.31 } 3.32 3.33 + private Filter<Type> errorFilter = new Filter<Type>() { 3.34 + @Override 3.35 + public boolean accepts(Type t) { 3.36 + return !t.isErroneous(); 3.37 + } 3.38 + }; 3.39 + 3.40 /** Instantiate undetermined type variable to the lub of all its lower bounds. 3.41 * Throw a NoInstanceException if this not possible. 3.42 */ 3.43 void minimizeInst(UndetVar that, Warner warn) throws NoInstanceException { 3.44 + List<Type> lobounds = Type.filter(that.lobounds, errorFilter); 3.45 if (that.inst == null) { 3.46 - if (that.lobounds.isEmpty()) 3.47 + if (lobounds.isEmpty()) 3.48 that.inst = syms.botType; 3.49 - else if (that.lobounds.tail.isEmpty()) 3.50 - that.inst = that.lobounds.head.isPrimitive() ? syms.errType : that.lobounds.head; 3.51 + else if (lobounds.tail.isEmpty()) 3.52 + that.inst = lobounds.head.isPrimitive() ? syms.errType : lobounds.head; 3.53 else { 3.54 - that.inst = types.lub(that.lobounds); 3.55 + that.inst = types.lub(lobounds); 3.56 } 3.57 if (that.inst == null || that.inst.tag == ERROR) 3.58 throw ambiguousNoInstanceException 3.59 .setMessage("no.unique.minimal.instance.exists", 3.60 - that.qtype, that.lobounds); 3.61 + that.qtype, lobounds); 3.62 // VGJ: sort of inlined maximizeInst() below. Adding 3.63 // bounds can cause lobounds that are above hibounds. 3.64 - if (that.hibounds.isEmpty()) 3.65 + List<Type> hibounds = Type.filter(that.hibounds, errorFilter); 3.66 + if (hibounds.isEmpty()) 3.67 return; 3.68 Type hb = null; 3.69 - if (that.hibounds.tail.isEmpty()) 3.70 - hb = that.hibounds.head; 3.71 - else for (List<Type> bs = that.hibounds; 3.72 + if (hibounds.tail.isEmpty()) 3.73 + hb = hibounds.head; 3.74 + else for (List<Type> bs = hibounds; 3.75 bs.nonEmpty() && hb == null; 3.76 bs = bs.tail) { 3.77 - if (isSubClass(bs.head, that.hibounds)) 3.78 + if (isSubClass(bs.head, hibounds)) 3.79 hb = types.fromUnknownFun.apply(bs.head); 3.80 } 3.81 if (hb == null || 3.82 - !types.isSubtypeUnchecked(hb, that.hibounds, warn) || 3.83 + !types.isSubtypeUnchecked(hb, hibounds, warn) || 3.84 !types.isSubtypeUnchecked(that.inst, hb, warn)) 3.85 throw ambiguousNoInstanceException; 3.86 } 3.87 @@ -528,7 +538,8 @@ 3.88 for (List<Type> tvs = tvars, args = arguments; 3.89 tvs.nonEmpty(); 3.90 tvs = tvs.tail, args = args.tail) { 3.91 - if (args.head instanceof UndetVar) continue; 3.92 + if (args.head instanceof UndetVar || 3.93 + tvars.head.getUpperBound().isErroneous()) continue; 3.94 List<Type> bounds = types.subst(types.getBounds((TypeVar)tvs.head), tvars, arguments); 3.95 if (!types.isSubtypeUnchecked(args.head, bounds, warn)) 3.96 throw invalidInstanceException
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/tools/javac/generics/inference/6943278/T6943278.java Mon Jan 24 15:44:15 2011 +0000 4.3 @@ -0,0 +1,12 @@ 4.4 +/** 4.5 + * @test /nodynamiccopyright/ 4.6 + * @bug 6943278 4.7 + * @summary spurious error message for inference and type-variable with erroneous bound 4.8 + * @compile/fail/ref=T6943278.out -XDrawDiagnostics -Xlint:unchecked T6943278.java 4.9 + */ 4.10 +class T6943278<X extends Number & NonExistentInterface> { 4.11 + <X> T6943278<X> m() { return null;} 4.12 + <X extends Number & NonExistentInterface> T6943278<X> m(X x) { return null;} 4.13 + T6943278<?> f1 = m(); 4.14 + T6943278<?> f2 = m(""); 4.15 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/tools/javac/generics/inference/6943278/T6943278.out Mon Jan 24 15:44:15 2011 +0000 5.3 @@ -0,0 +1,3 @@ 5.4 +T6943278.java:7:35: compiler.err.cant.resolve: kindname.class, NonExistentInterface, , 5.5 +T6943278.java:9:25: compiler.err.cant.resolve.location: kindname.class, NonExistentInterface, , , kindname.class, T6943278<X> 5.6 +2 errors