mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 11:04:34 +02:00
6943278: spurious error message for inference and type-variable with erroneous bound
Type-inference should ignore erroneous bounds Reviewed-by: jjg
This commit is contained in:
parent
a13fa350f1
commit
df54c56a04
5 changed files with 60 additions and 19 deletions
|
@ -365,6 +365,16 @@ public class Type implements PrimitiveType {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<Type> filter(List<Type> ts, Filter<Type> tf) {
|
||||||
|
ListBuffer<Type> buf = ListBuffer.lb();
|
||||||
|
for (Type t : ts) {
|
||||||
|
if (tf.accepts(t)) {
|
||||||
|
buf.append(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf.toList();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isSuperBound() { return false; }
|
public boolean isSuperBound() { return false; }
|
||||||
public boolean isExtendsBound() { return false; }
|
public boolean isExtendsBound() { return false; }
|
||||||
public boolean isUnbound() { return false; }
|
public boolean isUnbound() { return false; }
|
||||||
|
|
|
@ -800,7 +800,8 @@ public class Check {
|
||||||
Type actual = types.subst(args.head,
|
Type actual = types.subst(args.head,
|
||||||
type.tsym.type.getTypeArguments(),
|
type.tsym.type.getTypeArguments(),
|
||||||
tvars_buf.toList());
|
tvars_buf.toList());
|
||||||
if (!checkExtends(actual, (TypeVar)tvars.head)) {
|
if (!checkExtends(actual, (TypeVar)tvars.head) &&
|
||||||
|
!tvars.head.getUpperBound().isErroneous()) {
|
||||||
return args.head;
|
return args.head;
|
||||||
}
|
}
|
||||||
args = args.tail;
|
args = args.tail;
|
||||||
|
@ -808,11 +809,15 @@ public class Check {
|
||||||
}
|
}
|
||||||
|
|
||||||
args = type.getTypeArguments();
|
args = type.getTypeArguments();
|
||||||
|
tvars = tvars_buf.toList();
|
||||||
|
|
||||||
for (Type arg : types.capture(type).getTypeArguments()) {
|
for (Type arg : types.capture(type).getTypeArguments()) {
|
||||||
if (arg.tag == TYPEVAR && arg.getUpperBound().isErroneous()) {
|
if (arg.tag == TYPEVAR &&
|
||||||
|
arg.getUpperBound().isErroneous() &&
|
||||||
|
!tvars.head.getUpperBound().isErroneous()) {
|
||||||
return args.head;
|
return args.head;
|
||||||
}
|
}
|
||||||
|
tvars = tvars.tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -205,19 +205,20 @@ public class Infer {
|
||||||
* Throw a NoInstanceException if this not possible.
|
* Throw a NoInstanceException if this not possible.
|
||||||
*/
|
*/
|
||||||
void maximizeInst(UndetVar that, Warner warn) throws NoInstanceException {
|
void maximizeInst(UndetVar that, Warner warn) throws NoInstanceException {
|
||||||
|
List<Type> hibounds = Type.filter(that.hibounds, errorFilter);
|
||||||
if (that.inst == null) {
|
if (that.inst == null) {
|
||||||
if (that.hibounds.isEmpty())
|
if (hibounds.isEmpty())
|
||||||
that.inst = syms.objectType;
|
that.inst = syms.objectType;
|
||||||
else if (that.hibounds.tail.isEmpty())
|
else if (hibounds.tail.isEmpty())
|
||||||
that.inst = that.hibounds.head;
|
that.inst = hibounds.head;
|
||||||
else
|
else
|
||||||
that.inst = types.glb(that.hibounds);
|
that.inst = types.glb(hibounds);
|
||||||
}
|
}
|
||||||
if (that.inst == null ||
|
if (that.inst == null ||
|
||||||
that.inst.isErroneous())
|
that.inst.isErroneous())
|
||||||
throw ambiguousNoInstanceException
|
throw ambiguousNoInstanceException
|
||||||
.setMessage("no.unique.maximal.instance.exists",
|
.setMessage("no.unique.maximal.instance.exists",
|
||||||
that.qtype, that.hibounds);
|
that.qtype, hibounds);
|
||||||
}
|
}
|
||||||
//where
|
//where
|
||||||
private boolean isSubClass(Type t, final List<Type> ts) {
|
private boolean isSubClass(Type t, final List<Type> ts) {
|
||||||
|
@ -241,37 +242,46 @@ public class Infer {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Filter<Type> errorFilter = new Filter<Type>() {
|
||||||
|
@Override
|
||||||
|
public boolean accepts(Type t) {
|
||||||
|
return !t.isErroneous();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/** Instantiate undetermined type variable to the lub of all its lower bounds.
|
/** Instantiate undetermined type variable to the lub of all its lower bounds.
|
||||||
* Throw a NoInstanceException if this not possible.
|
* Throw a NoInstanceException if this not possible.
|
||||||
*/
|
*/
|
||||||
void minimizeInst(UndetVar that, Warner warn) throws NoInstanceException {
|
void minimizeInst(UndetVar that, Warner warn) throws NoInstanceException {
|
||||||
|
List<Type> lobounds = Type.filter(that.lobounds, errorFilter);
|
||||||
if (that.inst == null) {
|
if (that.inst == null) {
|
||||||
if (that.lobounds.isEmpty())
|
if (lobounds.isEmpty())
|
||||||
that.inst = syms.botType;
|
that.inst = syms.botType;
|
||||||
else if (that.lobounds.tail.isEmpty())
|
else if (lobounds.tail.isEmpty())
|
||||||
that.inst = that.lobounds.head.isPrimitive() ? syms.errType : that.lobounds.head;
|
that.inst = lobounds.head.isPrimitive() ? syms.errType : lobounds.head;
|
||||||
else {
|
else {
|
||||||
that.inst = types.lub(that.lobounds);
|
that.inst = types.lub(lobounds);
|
||||||
}
|
}
|
||||||
if (that.inst == null || that.inst.tag == ERROR)
|
if (that.inst == null || that.inst.tag == ERROR)
|
||||||
throw ambiguousNoInstanceException
|
throw ambiguousNoInstanceException
|
||||||
.setMessage("no.unique.minimal.instance.exists",
|
.setMessage("no.unique.minimal.instance.exists",
|
||||||
that.qtype, that.lobounds);
|
that.qtype, lobounds);
|
||||||
// VGJ: sort of inlined maximizeInst() below. Adding
|
// VGJ: sort of inlined maximizeInst() below. Adding
|
||||||
// bounds can cause lobounds that are above hibounds.
|
// bounds can cause lobounds that are above hibounds.
|
||||||
if (that.hibounds.isEmpty())
|
List<Type> hibounds = Type.filter(that.hibounds, errorFilter);
|
||||||
|
if (hibounds.isEmpty())
|
||||||
return;
|
return;
|
||||||
Type hb = null;
|
Type hb = null;
|
||||||
if (that.hibounds.tail.isEmpty())
|
if (hibounds.tail.isEmpty())
|
||||||
hb = that.hibounds.head;
|
hb = hibounds.head;
|
||||||
else for (List<Type> bs = that.hibounds;
|
else for (List<Type> bs = hibounds;
|
||||||
bs.nonEmpty() && hb == null;
|
bs.nonEmpty() && hb == null;
|
||||||
bs = bs.tail) {
|
bs = bs.tail) {
|
||||||
if (isSubClass(bs.head, that.hibounds))
|
if (isSubClass(bs.head, hibounds))
|
||||||
hb = types.fromUnknownFun.apply(bs.head);
|
hb = types.fromUnknownFun.apply(bs.head);
|
||||||
}
|
}
|
||||||
if (hb == null ||
|
if (hb == null ||
|
||||||
!types.isSubtypeUnchecked(hb, that.hibounds, warn) ||
|
!types.isSubtypeUnchecked(hb, hibounds, warn) ||
|
||||||
!types.isSubtypeUnchecked(that.inst, hb, warn))
|
!types.isSubtypeUnchecked(that.inst, hb, warn))
|
||||||
throw ambiguousNoInstanceException;
|
throw ambiguousNoInstanceException;
|
||||||
}
|
}
|
||||||
|
@ -528,7 +538,8 @@ public class Infer {
|
||||||
for (List<Type> tvs = tvars, args = arguments;
|
for (List<Type> tvs = tvars, args = arguments;
|
||||||
tvs.nonEmpty();
|
tvs.nonEmpty();
|
||||||
tvs = tvs.tail, args = args.tail) {
|
tvs = tvs.tail, args = args.tail) {
|
||||||
if (args.head instanceof UndetVar) continue;
|
if (args.head instanceof UndetVar ||
|
||||||
|
tvars.head.getUpperBound().isErroneous()) continue;
|
||||||
List<Type> bounds = types.subst(types.getBounds((TypeVar)tvs.head), tvars, arguments);
|
List<Type> bounds = types.subst(types.getBounds((TypeVar)tvs.head), tvars, arguments);
|
||||||
if (!types.isSubtypeUnchecked(args.head, bounds, warn))
|
if (!types.isSubtypeUnchecked(args.head, bounds, warn))
|
||||||
throw invalidInstanceException
|
throw invalidInstanceException
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
/**
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @bug 6943278
|
||||||
|
* @summary spurious error message for inference and type-variable with erroneous bound
|
||||||
|
* @compile/fail/ref=T6943278.out -XDrawDiagnostics -Xlint:unchecked T6943278.java
|
||||||
|
*/
|
||||||
|
class T6943278<X extends Number & NonExistentInterface> {
|
||||||
|
<X> T6943278<X> m() { return null;}
|
||||||
|
<X extends Number & NonExistentInterface> T6943278<X> m(X x) { return null;}
|
||||||
|
T6943278<?> f1 = m();
|
||||||
|
T6943278<?> f2 = m("");
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
T6943278.java:7:35: compiler.err.cant.resolve: kindname.class, NonExistentInterface, ,
|
||||||
|
T6943278.java:9:25: compiler.err.cant.resolve.location: kindname.class, NonExistentInterface, , , kindname.class, T6943278<X>
|
||||||
|
2 errors
|
Loading…
Add table
Add a link
Reference in a new issue