mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 02:54:35 +02:00
7177306: Regression: unchecked method call does not erase return type
Spurious extra call to Attr.checkMethod when method call is unchecked Reviewed-by: jjg, dlsmith
This commit is contained in:
parent
d4c5fca16a
commit
f49f25c60d
18 changed files with 379 additions and 68 deletions
|
@ -30,6 +30,10 @@ import java.util.Collections;
|
||||||
import com.sun.tools.javac.util.*;
|
import com.sun.tools.javac.util.*;
|
||||||
import com.sun.tools.javac.code.Symbol.*;
|
import com.sun.tools.javac.code.Symbol.*;
|
||||||
|
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import javax.lang.model.type.*;
|
import javax.lang.model.type.*;
|
||||||
|
|
||||||
import static com.sun.tools.javac.code.Flags.*;
|
import static com.sun.tools.javac.code.Flags.*;
|
||||||
|
@ -1168,22 +1172,55 @@ public class Type implements PrimitiveType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A class for instantiatable variables, for use during type
|
/** A class for inference variables, for use during method/diamond type
|
||||||
* inference.
|
* inference. An inference variable has upper/lower bounds and a set
|
||||||
|
* of equality constraints. Such bounds are set during subtyping, type-containment,
|
||||||
|
* type-equality checks, when the types being tested contain inference variables.
|
||||||
|
* A change listener can be attached to an inference variable, to receive notifications
|
||||||
|
* whenever the bounds of an inference variable change.
|
||||||
*/
|
*/
|
||||||
public static class UndetVar extends DelegatedType {
|
public static class UndetVar extends DelegatedType {
|
||||||
public List<Type> lobounds = List.nil();
|
|
||||||
public List<Type> hibounds = List.nil();
|
/** Inference variable change listener. The listener method is called
|
||||||
public List<Type> eq = List.nil();
|
* whenever a change to the inference variable's bounds occurs
|
||||||
|
*/
|
||||||
|
public interface UndetVarListener {
|
||||||
|
/** called when some inference variable bounds (of given kinds ibs) change */
|
||||||
|
void varChanged(UndetVar uv, Set<InferenceBound> ibs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inference variable bound kinds
|
||||||
|
*/
|
||||||
|
public enum InferenceBound {
|
||||||
|
/** upper bounds */
|
||||||
|
UPPER,
|
||||||
|
/** lower bounds */
|
||||||
|
LOWER,
|
||||||
|
/** equality constraints */
|
||||||
|
EQ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** inference variable bounds */
|
||||||
|
private Map<InferenceBound, List<Type>> bounds;
|
||||||
|
|
||||||
|
/** inference variable's inferred type (set from Infer.java) */
|
||||||
public Type inst = null;
|
public Type inst = null;
|
||||||
|
|
||||||
|
/** inference variable's change listener */
|
||||||
|
public UndetVarListener listener = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R,S> R accept(Type.Visitor<R,S> v, S s) {
|
public <R,S> R accept(Type.Visitor<R,S> v, S s) {
|
||||||
return v.visitUndetVar(this, s);
|
return v.visitUndetVar(this, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UndetVar(Type origin) {
|
public UndetVar(TypeVar origin, Types types) {
|
||||||
super(UNDETVAR, origin);
|
super(UNDETVAR, origin);
|
||||||
|
bounds = new EnumMap<InferenceBound, List<Type>>(InferenceBound.class);
|
||||||
|
bounds.put(InferenceBound.UPPER, types.getBounds(origin));
|
||||||
|
bounds.put(InferenceBound.LOWER, List.<Type>nil());
|
||||||
|
bounds.put(InferenceBound.EQ, List.<Type>nil());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
@ -1195,6 +1232,48 @@ public class Type implements PrimitiveType {
|
||||||
if (inst != null) return inst.baseType();
|
if (inst != null) return inst.baseType();
|
||||||
else return this;
|
else return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** get all bounds of a given kind */
|
||||||
|
public List<Type> getBounds(InferenceBound ib) {
|
||||||
|
return bounds.get(ib);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** add a bound of a given kind - this might trigger listener notification */
|
||||||
|
public void addBound(InferenceBound ib, Type bound, Types types) {
|
||||||
|
List<Type> prevBounds = bounds.get(ib);
|
||||||
|
for (Type b : prevBounds) {
|
||||||
|
if (types.isSameType(b, bound)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bounds.put(ib, prevBounds.prepend(bound));
|
||||||
|
notifyChange(EnumSet.of(ib));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** replace types in all bounds - this might trigger listener notification */
|
||||||
|
public void substBounds(List<Type> from, List<Type> to, Types types) {
|
||||||
|
EnumSet<InferenceBound> changed = EnumSet.noneOf(InferenceBound.class);
|
||||||
|
Map<InferenceBound, List<Type>> bounds2 = new EnumMap<InferenceBound, List<Type>>(InferenceBound.class);
|
||||||
|
for (Map.Entry<InferenceBound, List<Type>> _entry : bounds.entrySet()) {
|
||||||
|
InferenceBound ib = _entry.getKey();
|
||||||
|
List<Type> prevBounds = _entry.getValue();
|
||||||
|
List<Type> newBounds = types.subst(prevBounds, from, to);
|
||||||
|
bounds2.put(ib, newBounds);
|
||||||
|
if (prevBounds != newBounds) {
|
||||||
|
changed.add(ib);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!changed.isEmpty()) {
|
||||||
|
bounds = bounds2;
|
||||||
|
notifyChange(changed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyChange(EnumSet<InferenceBound> ibs) {
|
||||||
|
if (listener != null) {
|
||||||
|
listener.varChanged(this, ibs);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Represents VOID or NONE.
|
/** Represents VOID or NONE.
|
||||||
|
|
|
@ -34,6 +34,7 @@ import com.sun.tools.javac.util.List;
|
||||||
import com.sun.tools.javac.jvm.ClassReader;
|
import com.sun.tools.javac.jvm.ClassReader;
|
||||||
import com.sun.tools.javac.code.Attribute.RetentionPolicy;
|
import com.sun.tools.javac.code.Attribute.RetentionPolicy;
|
||||||
import com.sun.tools.javac.code.Lint.LintCategory;
|
import com.sun.tools.javac.code.Lint.LintCategory;
|
||||||
|
import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
|
||||||
import com.sun.tools.javac.comp.Check;
|
import com.sun.tools.javac.comp.Check;
|
||||||
|
|
||||||
import static com.sun.tools.javac.code.Scope.*;
|
import static com.sun.tools.javac.code.Scope.*;
|
||||||
|
@ -510,7 +511,7 @@ public class Types {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
t.hibounds = t.hibounds.prepend(s);
|
t.addBound(InferenceBound.UPPER, s, Types.this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -578,7 +579,7 @@ public class Types {
|
||||||
undet.qtype == s ||
|
undet.qtype == s ||
|
||||||
s.tag == ERROR ||
|
s.tag == ERROR ||
|
||||||
s.tag == BOT) return true;
|
s.tag == BOT) return true;
|
||||||
undet.lobounds = undet.lobounds.prepend(s);
|
undet.addBound(InferenceBound.LOWER, s, this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -723,7 +724,7 @@ public class Types {
|
||||||
if (t == s || t.qtype == s || s.tag == ERROR || s.tag == UNKNOWN)
|
if (t == s || t.qtype == s || s.tag == ERROR || s.tag == UNKNOWN)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
t.eq = t.eq.prepend(s);
|
t.addBound(InferenceBound.EQ, s, Types.this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -735,19 +736,6 @@ public class Types {
|
||||||
};
|
};
|
||||||
// </editor-fold>
|
// </editor-fold>
|
||||||
|
|
||||||
// <editor-fold defaultstate="collapsed" desc="fromUnknownFun">
|
|
||||||
/**
|
|
||||||
* A mapping that turns all unknown types in this type to fresh
|
|
||||||
* unknown variables.
|
|
||||||
*/
|
|
||||||
public Mapping fromUnknownFun = new Mapping("fromUnknownFun") {
|
|
||||||
public Type apply(Type t) {
|
|
||||||
if (t.tag == UNKNOWN) return new UndetVar(t);
|
|
||||||
else return t.map(this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// </editor-fold>
|
|
||||||
|
|
||||||
// <editor-fold defaultstate="collapsed" desc="Contains Type">
|
// <editor-fold defaultstate="collapsed" desc="Contains Type">
|
||||||
public boolean containedBy(Type t, Type s) {
|
public boolean containedBy(Type t, Type s) {
|
||||||
switch (t.tag) {
|
switch (t.tag) {
|
||||||
|
@ -759,12 +747,12 @@ public class Types {
|
||||||
case UNBOUND: //similar to ? extends Object
|
case UNBOUND: //similar to ? extends Object
|
||||||
case EXTENDS: {
|
case EXTENDS: {
|
||||||
Type bound = upperBound(s);
|
Type bound = upperBound(s);
|
||||||
undetvar.hibounds = undetvar.hibounds.prepend(bound);
|
undetvar.addBound(InferenceBound.UPPER, bound, this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SUPER: {
|
case SUPER: {
|
||||||
Type bound = lowerBound(s);
|
Type bound = lowerBound(s);
|
||||||
undetvar.lobounds = undetvar.lobounds.prepend(bound);
|
undetvar.addBound(InferenceBound.LOWER, bound, this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ package com.sun.tools.javac.comp;
|
||||||
import com.sun.tools.javac.code.*;
|
import com.sun.tools.javac.code.*;
|
||||||
import com.sun.tools.javac.code.Symbol.*;
|
import com.sun.tools.javac.code.Symbol.*;
|
||||||
import com.sun.tools.javac.code.Type.*;
|
import com.sun.tools.javac.code.Type.*;
|
||||||
|
import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
|
||||||
import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
|
import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
|
||||||
import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
|
import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
|
||||||
import com.sun.tools.javac.tree.JCTree;
|
import com.sun.tools.javac.tree.JCTree;
|
||||||
|
@ -39,6 +40,7 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import static com.sun.tools.javac.code.TypeTags.*;
|
import static com.sun.tools.javac.code.TypeTags.*;
|
||||||
|
|
||||||
|
@ -120,8 +122,8 @@ public class Infer {
|
||||||
* Throw a NoInstanceException if this not possible.
|
* Throw a NoInstanceException if this not possible.
|
||||||
*/
|
*/
|
||||||
void maximizeInst(UndetVar that, Warner warn) throws InferenceException {
|
void maximizeInst(UndetVar that, Warner warn) throws InferenceException {
|
||||||
List<Type> hibounds = Type.filter(that.hibounds, boundFilter);
|
List<Type> hibounds = Type.filter(that.getBounds(InferenceBound.UPPER), boundFilter);
|
||||||
if (that.eq.isEmpty()) {
|
if (that.getBounds(InferenceBound.EQ).isEmpty()) {
|
||||||
if (hibounds.isEmpty())
|
if (hibounds.isEmpty())
|
||||||
that.inst = syms.objectType;
|
that.inst = syms.objectType;
|
||||||
else if (hibounds.tail.isEmpty())
|
else if (hibounds.tail.isEmpty())
|
||||||
|
@ -129,7 +131,7 @@ public class Infer {
|
||||||
else
|
else
|
||||||
that.inst = types.glb(hibounds);
|
that.inst = types.glb(hibounds);
|
||||||
} else {
|
} else {
|
||||||
that.inst = that.eq.head;
|
that.inst = that.getBounds(InferenceBound.EQ).head;
|
||||||
}
|
}
|
||||||
if (that.inst == null ||
|
if (that.inst == null ||
|
||||||
that.inst.isErroneous())
|
that.inst.isErroneous())
|
||||||
|
@ -149,8 +151,8 @@ public class Infer {
|
||||||
* Throw a NoInstanceException if this not possible.
|
* Throw a NoInstanceException if this not possible.
|
||||||
*/
|
*/
|
||||||
void minimizeInst(UndetVar that, Warner warn) throws InferenceException {
|
void minimizeInst(UndetVar that, Warner warn) throws InferenceException {
|
||||||
List<Type> lobounds = Type.filter(that.lobounds, boundFilter);
|
List<Type> lobounds = Type.filter(that.getBounds(InferenceBound.LOWER), boundFilter);
|
||||||
if (that.eq.isEmpty()) {
|
if (that.getBounds(InferenceBound.EQ).isEmpty()) {
|
||||||
if (lobounds.isEmpty()) {
|
if (lobounds.isEmpty()) {
|
||||||
//do nothing - the inference variable is under-constrained
|
//do nothing - the inference variable is under-constrained
|
||||||
return;
|
return;
|
||||||
|
@ -164,7 +166,7 @@ public class Infer {
|
||||||
.setMessage("no.unique.minimal.instance.exists",
|
.setMessage("no.unique.minimal.instance.exists",
|
||||||
that.qtype, lobounds);
|
that.qtype, lobounds);
|
||||||
} else {
|
} else {
|
||||||
that.inst = that.eq.head;
|
that.inst = that.getBounds(InferenceBound.EQ).head;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,7 +203,8 @@ public class Infer {
|
||||||
boolean stuck = true;
|
boolean stuck = true;
|
||||||
for (Type t : inferenceContext.undetvars) {
|
for (Type t : inferenceContext.undetvars) {
|
||||||
UndetVar uv = (UndetVar)t;
|
UndetVar uv = (UndetVar)t;
|
||||||
if (uv.inst == null && (uv.eq.nonEmpty() || !inferenceContext.free(uv.hibounds))) {
|
if (uv.inst == null && (uv.getBounds(InferenceBound.EQ).nonEmpty() ||
|
||||||
|
!inferenceContext.free(uv.getBounds(InferenceBound.UPPER)))) {
|
||||||
maximizeInst((UndetVar)t, warn);
|
maximizeInst((UndetVar)t, warn);
|
||||||
stuck = false;
|
stuck = false;
|
||||||
}
|
}
|
||||||
|
@ -219,7 +222,7 @@ public class Infer {
|
||||||
//variables in remaining upper bounds and continue
|
//variables in remaining upper bounds and continue
|
||||||
for (Type t : inferenceContext.undetvars) {
|
for (Type t : inferenceContext.undetvars) {
|
||||||
UndetVar uv = (UndetVar)t;
|
UndetVar uv = (UndetVar)t;
|
||||||
uv.hibounds = inferenceContext.asInstTypes(uv.hibounds, types);
|
uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), types);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,7 +238,7 @@ public class Infer {
|
||||||
UndetVar uv = (UndetVar)t;
|
UndetVar uv = (UndetVar)t;
|
||||||
if (uv.inst == null) {
|
if (uv.inst == null) {
|
||||||
TypeSymbol fresh_tvar = new TypeSymbol(Flags.SYNTHETIC, uv.qtype.tsym.name, null, uv.qtype.tsym.owner);
|
TypeSymbol fresh_tvar = new TypeSymbol(Flags.SYNTHETIC, uv.qtype.tsym.name, null, uv.qtype.tsym.owner);
|
||||||
fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.hibounds), null);
|
fresh_tvar.type = new TypeVar(fresh_tvar, types.makeCompoundType(uv.getBounds(InferenceBound.UPPER)), null);
|
||||||
todo.append(uv);
|
todo.append(uv);
|
||||||
uv.inst = fresh_tvar.type;
|
uv.inst = fresh_tvar.type;
|
||||||
}
|
}
|
||||||
|
@ -267,7 +270,7 @@ public class Infer {
|
||||||
boolean useVarargs,
|
boolean useVarargs,
|
||||||
Warner warn) throws InferenceException {
|
Warner warn) throws InferenceException {
|
||||||
//-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
|
//-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
|
||||||
final InferenceContext inferenceContext = new InferenceContext(tvars, types);
|
final InferenceContext inferenceContext = new InferenceContext(tvars, this);
|
||||||
inferenceException.clear();
|
inferenceException.clear();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -286,7 +289,7 @@ public class Infer {
|
||||||
List<Type> restvars = inferenceContext.restvars();
|
List<Type> restvars = inferenceContext.restvars();
|
||||||
|
|
||||||
if (!restvars.isEmpty()) {
|
if (!restvars.isEmpty()) {
|
||||||
if (resultInfo != null) {
|
if (resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
|
||||||
instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo, warn);
|
instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo, warn);
|
||||||
checkWithinBounds(inferenceContext, warn);
|
checkWithinBounds(inferenceContext, warn);
|
||||||
mt = (MethodType)inferenceContext.asInstType(mt, types);
|
mt = (MethodType)inferenceContext.asInstType(mt, types);
|
||||||
|
@ -332,34 +335,58 @@ public class Infer {
|
||||||
/** check that type parameters are within their bounds.
|
/** check that type parameters are within their bounds.
|
||||||
*/
|
*/
|
||||||
void checkWithinBounds(InferenceContext inferenceContext,
|
void checkWithinBounds(InferenceContext inferenceContext,
|
||||||
Warner warn)
|
Warner warn) throws InferenceException {
|
||||||
throws InferenceException {
|
//step 1 - check compatibility of instantiated type w.r.t. initial bounds
|
||||||
List<Type> tvars = inferenceContext.inferenceVars();
|
|
||||||
for (Type t : inferenceContext.undetvars) {
|
for (Type t : inferenceContext.undetvars) {
|
||||||
UndetVar uv = (UndetVar)t;
|
UndetVar uv = (UndetVar)t;
|
||||||
uv.hibounds = inferenceContext.asInstTypes(uv.hibounds, types);
|
uv.substBounds(inferenceContext.inferenceVars(), inferenceContext.instTypes(), types);
|
||||||
uv.lobounds = inferenceContext.asInstTypes(uv.lobounds, types);
|
|
||||||
uv.eq = inferenceContext.asInstTypes(uv.eq, types);
|
|
||||||
checkCompatibleUpperBounds(uv, inferenceContext.inferenceVars());
|
checkCompatibleUpperBounds(uv, inferenceContext.inferenceVars());
|
||||||
if (!inferenceContext.restvars().contains(tvars.head)) {
|
if (!inferenceContext.restvars().contains(uv.qtype)) {
|
||||||
Type inst = inferenceContext.asInstType(t, types);
|
Type inst = inferenceContext.asInstType(t, types);
|
||||||
for (Type u : uv.hibounds) {
|
for (Type u : uv.getBounds(InferenceBound.UPPER)) {
|
||||||
if (!types.isSubtypeUnchecked(inst, inferenceContext.asFree(u, types), warn)) {
|
if (!types.isSubtypeUnchecked(inst, inferenceContext.asFree(u, types), warn)) {
|
||||||
reportBoundError(uv, BoundErrorKind.UPPER);
|
reportBoundError(uv, BoundErrorKind.UPPER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Type l : uv.lobounds) {
|
for (Type l : uv.getBounds(InferenceBound.LOWER)) {
|
||||||
if (!types.isSubtypeUnchecked(inferenceContext.asFree(l, types), inst, warn)) {
|
Assert.check(!inferenceContext.free(l));
|
||||||
|
if (!types.isSubtypeUnchecked(l, inst, warn)) {
|
||||||
reportBoundError(uv, BoundErrorKind.LOWER);
|
reportBoundError(uv, BoundErrorKind.LOWER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Type e : uv.eq) {
|
for (Type e : uv.getBounds(InferenceBound.EQ)) {
|
||||||
if (!types.isSameType(inst, inferenceContext.asFree(e, types))) {
|
Assert.check(!inferenceContext.free(e));
|
||||||
|
if (!types.isSameType(inst, e)) {
|
||||||
reportBoundError(uv, BoundErrorKind.EQ);
|
reportBoundError(uv, BoundErrorKind.EQ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tvars = tvars.tail;
|
}
|
||||||
|
|
||||||
|
//step 2 - check that eq bounds are consistent w.r.t. eq/lower bounds
|
||||||
|
for (Type t : inferenceContext.undetvars) {
|
||||||
|
UndetVar uv = (UndetVar)t;
|
||||||
|
//check eq bounds consistency
|
||||||
|
Type eq = null;
|
||||||
|
for (Type e : uv.getBounds(InferenceBound.EQ)) {
|
||||||
|
Assert.check(!inferenceContext.free(e));
|
||||||
|
if (eq != null && !types.isSameType(e, eq)) {
|
||||||
|
reportBoundError(uv, BoundErrorKind.EQ);
|
||||||
|
}
|
||||||
|
eq = e;
|
||||||
|
for (Type l : uv.getBounds(InferenceBound.LOWER)) {
|
||||||
|
Assert.check(!inferenceContext.free(l));
|
||||||
|
if (!types.isSubtypeUnchecked(l, e, warn)) {
|
||||||
|
reportBoundError(uv, BoundErrorKind.BAD_EQ_LOWER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Type u : uv.getBounds(InferenceBound.UPPER)) {
|
||||||
|
if (inferenceContext.free(u)) continue;
|
||||||
|
if (!types.isSubtypeUnchecked(e, u, warn)) {
|
||||||
|
reportBoundError(uv, BoundErrorKind.BAD_EQ_UPPER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,7 +394,7 @@ public class Infer {
|
||||||
// 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.
|
||||||
ListBuffer<Type> hiboundsNoVars = ListBuffer.lb();
|
ListBuffer<Type> hiboundsNoVars = ListBuffer.lb();
|
||||||
for (Type t : Type.filter(uv.hibounds, boundFilter)) {
|
for (Type t : Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter)) {
|
||||||
if (!t.containsAny(tvars)) {
|
if (!t.containsAny(tvars)) {
|
||||||
hiboundsNoVars.append(t);
|
hiboundsNoVars.append(t);
|
||||||
}
|
}
|
||||||
|
@ -388,25 +415,43 @@ public class Infer {
|
||||||
BAD_UPPER() {
|
BAD_UPPER() {
|
||||||
@Override
|
@Override
|
||||||
InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
|
InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
|
||||||
return ex.setMessage("incompatible.upper.bounds", uv.qtype, uv.hibounds);
|
return ex.setMessage("incompatible.upper.bounds", uv.qtype,
|
||||||
|
uv.getBounds(InferenceBound.UPPER));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
BAD_EQ_UPPER() {
|
||||||
|
@Override
|
||||||
|
InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
|
||||||
|
return ex.setMessage("incompatible.eq.upper.bounds", uv.qtype,
|
||||||
|
uv.getBounds(InferenceBound.EQ), uv.getBounds(InferenceBound.UPPER));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
BAD_EQ_LOWER() {
|
||||||
|
@Override
|
||||||
|
InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
|
||||||
|
return ex.setMessage("incompatible.eq.lower.bounds", uv.qtype,
|
||||||
|
uv.getBounds(InferenceBound.EQ), uv.getBounds(InferenceBound.LOWER));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
UPPER() {
|
UPPER() {
|
||||||
@Override
|
@Override
|
||||||
InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
|
InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
|
||||||
return ex.setMessage("inferred.do.not.conform.to.upper.bounds", uv.inst, uv.hibounds);
|
return ex.setMessage("inferred.do.not.conform.to.upper.bounds", uv.inst,
|
||||||
|
uv.getBounds(InferenceBound.UPPER));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
LOWER() {
|
LOWER() {
|
||||||
@Override
|
@Override
|
||||||
InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
|
InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
|
||||||
return ex.setMessage("inferred.do.not.conform.to.lower.bounds", uv.inst, uv.lobounds);
|
return ex.setMessage("inferred.do.not.conform.to.lower.bounds", uv.inst,
|
||||||
|
uv.getBounds(InferenceBound.LOWER));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
EQ() {
|
EQ() {
|
||||||
@Override
|
@Override
|
||||||
InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
|
InapplicableMethodException setMessage(InferenceException ex, UndetVar uv) {
|
||||||
return ex.setMessage("inferred.do.not.conform.to.eq.bounds", uv.inst, uv.eq);
|
return ex.setMessage("inferred.do.not.conform.to.eq.bounds", uv.inst,
|
||||||
|
uv.getBounds(InferenceBound.EQ));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -480,9 +525,9 @@ public class Infer {
|
||||||
* Mapping that turns inference variables into undet vars
|
* Mapping that turns inference variables into undet vars
|
||||||
* (used by inference context)
|
* (used by inference context)
|
||||||
*/
|
*/
|
||||||
static Mapping fromTypeVarFun = new Mapping("fromTypeVarFun") {
|
Mapping fromTypeVarFun = new Mapping("fromTypeVarFun") {
|
||||||
public Type apply(Type t) {
|
public Type apply(Type t) {
|
||||||
if (t.tag == TYPEVAR) return new UndetVar(t);
|
if (t.tag == TYPEVAR) return new UndetVar((TypeVar)t, types);
|
||||||
else return t.map(this);
|
else return t.map(this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -517,13 +562,9 @@ public class Infer {
|
||||||
|
|
||||||
List<FreeTypeListener> freetypeListeners = List.nil();
|
List<FreeTypeListener> freetypeListeners = List.nil();
|
||||||
|
|
||||||
public InferenceContext(List<Type> inferencevars, Types types) {
|
public InferenceContext(List<Type> inferencevars, Infer infer) {
|
||||||
this.undetvars = Type.map(inferencevars, fromTypeVarFun);
|
this.undetvars = Type.map(inferencevars, infer.fromTypeVarFun);
|
||||||
this.inferencevars = inferencevars;
|
this.inferencevars = inferencevars;
|
||||||
for (Type t : this.undetvars) {
|
|
||||||
UndetVar uv = (UndetVar)t;
|
|
||||||
uv.hibounds = types.getBounds((TypeVar)uv.qtype);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -669,5 +710,5 @@ public class Infer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final InferenceContext emptyContext = new InferenceContext(List.<Type>nil(), types);
|
final InferenceContext emptyContext = new InferenceContext(List.<Type>nil(), this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -737,7 +737,7 @@ public class Resolve {
|
||||||
return attr.new ResultInfo(VAL, to, checkContext) {
|
return attr.new ResultInfo(VAL, to, checkContext) {
|
||||||
@Override
|
@Override
|
||||||
protected Type check(DiagnosticPosition pos, Type found) {
|
protected Type check(DiagnosticPosition pos, Type found) {
|
||||||
return super.check(pos, chk.checkNonVoid(pos, types.capture(types.upperBound(found))));
|
return super.check(pos, chk.checkNonVoid(pos, types.capture(types.upperBound(found.baseType()))));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1652,6 +1652,18 @@ compiler.misc.no.unique.minimal.instance.exists=\
|
||||||
compiler.misc.incompatible.upper.bounds=\
|
compiler.misc.incompatible.upper.bounds=\
|
||||||
inference variable {0} has incompatible upper bounds {1}
|
inference variable {0} has incompatible upper bounds {1}
|
||||||
|
|
||||||
|
# 0: type, 1: list of type, 2: list of type
|
||||||
|
compiler.misc.incompatible.eq.upper.bounds=\
|
||||||
|
inference variable {0} has incompatible bounds\n\
|
||||||
|
equality constraints: {1}\n\
|
||||||
|
upper bounds: {2}
|
||||||
|
|
||||||
|
# 0: type, 1: list of type, 2: list of type
|
||||||
|
compiler.misc.incompatible.eq.lower.bounds=\
|
||||||
|
inference variable {0} has incompatible bounds\n\
|
||||||
|
equality constraints: {1}\n\
|
||||||
|
lower bounds: {2}
|
||||||
|
|
||||||
# 0: list of type, 1: type, 2: type
|
# 0: list of type, 1: type, 2: type
|
||||||
compiler.misc.infer.no.conforming.instance.exists=\
|
compiler.misc.infer.no.conforming.instance.exists=\
|
||||||
no instance(s) of type variable(s) {0} exist so that {1} conforms to {2}
|
no instance(s) of type variable(s) {0} exist so that {1} conforms to {2}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
T6758789b.java:16:11: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T6758789a.Foo, T6758789a.Foo<java.lang.Object>
|
T6758789b.java:16:11: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T6758789a.Foo, T6758789a.Foo<X>
|
||||||
T6758789b.java:16:10: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, T6758789a.Foo<X>, T6758789a.Foo, kindname.class, T6758789a
|
T6758789b.java:16:10: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, T6758789a.Foo<X>, T6758789a.Foo, kindname.class, T6758789a
|
||||||
- compiler.err.warnings.and.werror
|
- compiler.err.warnings.and.werror
|
||||||
1 error
|
1 error
|
||||||
|
|
|
@ -65,6 +65,7 @@ compiler.misc.kindname.static
|
||||||
compiler.misc.kindname.type.variable
|
compiler.misc.kindname.type.variable
|
||||||
compiler.misc.kindname.type.variable.bound
|
compiler.misc.kindname.type.variable.bound
|
||||||
compiler.misc.kindname.value
|
compiler.misc.kindname.value
|
||||||
|
compiler.misc.incompatible.eq.lower.bounds # cannot happen?
|
||||||
compiler.misc.no.unique.minimal.instance.exists
|
compiler.misc.no.unique.minimal.instance.exists
|
||||||
compiler.misc.resume.abort # prompt for a response
|
compiler.misc.resume.abort # prompt for a response
|
||||||
compiler.misc.source.unavailable # DiagnosticSource
|
compiler.misc.source.unavailable # DiagnosticSource
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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.symbol.1
|
||||||
|
//key: compiler.misc.incompatible.eq.upper.bounds
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class IncompatibleEqUpperBounds {
|
||||||
|
<S, T extends List<S>> void m(List<? super S> s1, T s2) { }
|
||||||
|
|
||||||
|
void test(List<Integer> li, List<String> ls) {
|
||||||
|
m(li, ls);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,14 @@
|
||||||
T7015430.java:41:15: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.Exception>
|
T7015430.java:41:15: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<E>
|
||||||
T7015430.java:41:14: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
|
T7015430.java:41:14: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
|
||||||
T7015430.java:50:42: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
|
T7015430.java:50:42: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
|
||||||
T7015430.java:50:41: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
|
T7015430.java:50:41: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
|
||||||
T7015430.java:68:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.Exception>
|
T7015430.java:68:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<E>
|
||||||
T7015430.java:68:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
|
T7015430.java:68:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
|
||||||
T7015430.java:77:40: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
|
T7015430.java:77:40: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
|
||||||
T7015430.java:77:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
|
T7015430.java:77:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
|
||||||
T7015430.java:104:41: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
|
T7015430.java:104:41: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
|
||||||
T7015430.java:104:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
|
T7015430.java:104:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
|
||||||
T7015430.java:113:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.Exception>
|
T7015430.java:113:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<E>
|
||||||
T7015430.java:113:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
|
T7015430.java:113:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
|
||||||
T7015430.java:41:14: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
|
T7015430.java:41:14: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
|
||||||
T7015430.java:68:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
|
T7015430.java:68:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
T7151802.java:14:31: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get1, Z, T7151802.Foo, kindname.class, T7151802
|
T7151802.java:14:31: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get1, Z, T7151802.Foo, kindname.class, T7151802
|
||||||
T7151802.java:22:31: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T7151802.Foo, T7151802.Foo<java.lang.Object>
|
T7151802.java:22:31: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T7151802.Foo, T7151802.Foo<Z>
|
||||||
T7151802.java:22:30: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get3, T7151802.Foo<Z>, T7151802.Foo, kindname.class, T7151802
|
T7151802.java:22:30: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get3, T7151802.Foo<Z>, T7151802.Foo, kindname.class, T7151802
|
||||||
T7151802.java:30:36: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get5, compiler.misc.no.args, compiler.misc.no.args, kindname.class, T7151802
|
T7151802.java:30:36: compiler.warn.unchecked.meth.invocation.applied: kindname.method, get5, compiler.misc.no.args, compiler.misc.no.args, kindname.class, T7151802
|
||||||
T7151802.java:38:32: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T7151802.Foo, T7151802.Foo<java.lang.String>
|
T7151802.java:38:32: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T7151802.Foo, T7151802.Foo<java.lang.String>
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/**
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @bug 7177306
|
||||||
|
* @summary Regression: unchecked method call does not erase return type
|
||||||
|
* @compile/fail/ref=T7177306a.out -Werror -Xlint:unchecked -XDrawDiagnostics T7177306a.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class T7177306a<A> {
|
||||||
|
|
||||||
|
public static void test(List l) {
|
||||||
|
T7177306a<Object> to = m(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E> T7177306a<String> m(List<E> le) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
T7177306a.java:13:34: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.util.List, java.util.List<E>
|
||||||
|
T7177306a.java:13:33: compiler.warn.unchecked.meth.invocation.applied: kindname.method, m, java.util.List<E>, java.util.List, kindname.class, T7177306a
|
||||||
|
T7177306a.java:13:33: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), T7177306a, T7177306a<java.lang.Object>
|
||||||
|
- compiler.err.warnings.and.werror
|
||||||
|
1 error
|
||||||
|
3 warnings
|
|
@ -0,0 +1,18 @@
|
||||||
|
/**
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @bug 7177306
|
||||||
|
* @summary Regression: unchecked method call does not erase return type
|
||||||
|
* @compile/fail/ref=T7177306b.out -Werror -Xlint:unchecked -XDrawDiagnostics T7177306b.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class T7177306b {
|
||||||
|
|
||||||
|
<T, S extends List<T>> List<T> m(List<? super T> arg1, S arg2, Class<Object> arg3) { return arg2; }
|
||||||
|
|
||||||
|
void test(List<Integer> li, List<String> ls, Class c) {
|
||||||
|
m(li, ls, c);
|
||||||
|
// should fail, because of bounds T <: Integer, S :> List<String>
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
T7177306b.java:15:9: compiler.err.cant.apply.symbol.1: kindname.method, m, java.util.List<? super T>,S,java.lang.Class<java.lang.Object>, java.util.List<java.lang.Integer>,java.util.List<java.lang.String>,java.lang.Class, kindname.class, T7177306b, (compiler.misc.incompatible.eq.upper.bounds: T, java.lang.String, java.lang.Integer,java.lang.Object)
|
||||||
|
1 error
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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 7177306
|
||||||
|
* @summary Regression: unchecked method call does not erase return type
|
||||||
|
*/
|
||||||
|
public class T7177306c {
|
||||||
|
|
||||||
|
static <T> T m(T t) { return (T)"Null"; }
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
if (m("NonNullConst") != "Null") {
|
||||||
|
throw new AssertionError("should not get there!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012, 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 7177306
|
||||||
|
* @summary Regression: unchecked method call does not erase return type
|
||||||
|
*/
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class T7177306d {
|
||||||
|
|
||||||
|
static int assertionCount = 0;
|
||||||
|
|
||||||
|
static void assertTrue(boolean cond) {
|
||||||
|
if (!cond) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
assertionCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static <T, S extends List<T>> void m(List<? super T> arg1, S arg2, Class<Object> arg3) { assertTrue(false); }
|
||||||
|
static void m(Object o1, Object o2, Object o3) { assertTrue(true); }
|
||||||
|
|
||||||
|
static void test(List<Integer> li, List<String> ls, Class c) {
|
||||||
|
m(li, ls, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
test(null, null, null);
|
||||||
|
assertTrue(assertionCount == 1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
/**
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @bug 7177306
|
||||||
|
* @summary Regression: unchecked method call does not erase return type
|
||||||
|
* @compile/fail/ref=T7177306e.out -XDrawDiagnostics T7177306e.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class T7177306e {
|
||||||
|
|
||||||
|
<Z, U extends List<Z>> void m(List<U> lu) { }
|
||||||
|
|
||||||
|
void test(List<List<?>> llw) {
|
||||||
|
m(llw);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
T7177306e.java:15:9: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.util.List<?>, java.util.List<compiler.misc.type.captureof: 1, ?>)
|
||||||
|
1 error
|
Loading…
Add table
Add a link
Reference in a new issue