提交 193665c0 编写于 作者: M mcimadamore

6943278: spurious error message for inference and type-variable with erroneous bound

Summary: type-inference should ignore erroneous bounds
Reviewed-by: jjg
上级 3db6b12a
...@@ -365,6 +365,16 @@ public class Type implements PrimitiveType { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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
......
/**
* @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("");
}
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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册