7015430: Incorrect thrown type determined for unchecked invocations
Thrown types do not get updated after 15.12.2.8, and do not get erased as per 15.12.2.6 Reviewed-by: jjg, dlsmith
This commit is contained in:
parent
78ebde094c
commit
32216fc797
@ -2806,7 +2806,7 @@ public class Attr extends JCTree.Visitor {
|
|||||||
sym.location());
|
sym.location());
|
||||||
owntype = new MethodType(owntype.getParameterTypes(),
|
owntype = new MethodType(owntype.getParameterTypes(),
|
||||||
types.erasure(owntype.getReturnType()),
|
types.erasure(owntype.getReturnType()),
|
||||||
owntype.getThrownTypes(),
|
types.erasure(owntype.getThrownTypes()),
|
||||||
syms.methodClass);
|
syms.methodClass);
|
||||||
}
|
}
|
||||||
if (useVarargs) {
|
if (useVarargs) {
|
||||||
|
@ -465,10 +465,9 @@ public class Infer {
|
|||||||
// quantify result type with them
|
// quantify result type with them
|
||||||
final List<Type> inferredTypes = insttypes.toList();
|
final List<Type> inferredTypes = insttypes.toList();
|
||||||
final List<Type> all_tvars = tvars; //this is the wrong tvars
|
final List<Type> all_tvars = tvars; //this is the wrong tvars
|
||||||
final MethodType mt2 = new MethodType(mt.argtypes, null, mt.thrown, syms.methodClass);
|
return new UninferredMethodType(mt, restvars.toList()) {
|
||||||
mt2.restype = new ForAll(restvars.toList(), mt.restype) {
|
|
||||||
@Override
|
@Override
|
||||||
public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) {
|
List<Type> getConstraints(TypeVar tv, ConstraintKind ck) {
|
||||||
for (Type t : restundet.toList()) {
|
for (Type t : restundet.toList()) {
|
||||||
UndetVar uv = (UndetVar)t;
|
UndetVar uv = (UndetVar)t;
|
||||||
if (uv.qtype == tv) {
|
if (uv.qtype == tv) {
|
||||||
@ -481,21 +480,17 @@ public class Infer {
|
|||||||
}
|
}
|
||||||
return List.nil();
|
return List.nil();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type inst(List<Type> inferred, Types types) throws NoInstanceException {
|
void check(List<Type> inferred, Types types) throws NoInstanceException {
|
||||||
List<Type> formals = types.subst(mt2.argtypes, tvars, inferred);
|
|
||||||
// check that actuals conform to inferred formals
|
// check that actuals conform to inferred formals
|
||||||
checkArgumentsAcceptable(env, capturedArgs, formals, allowBoxing, useVarargs, warn);
|
checkArgumentsAcceptable(env, capturedArgs, getParameterTypes(), allowBoxing, useVarargs, warn);
|
||||||
// check that inferred bounds conform to their bounds
|
// check that inferred bounds conform to their bounds
|
||||||
checkWithinBounds(all_tvars,
|
checkWithinBounds(all_tvars,
|
||||||
types.subst(inferredTypes, tvars, inferred), warn);
|
types.subst(inferredTypes, tvars, inferred), warn);
|
||||||
if (useVarargs) {
|
if (useVarargs) {
|
||||||
chk.checkVararg(env.tree.pos(), formals, msym);
|
chk.checkVararg(env.tree.pos(), getParameterTypes(), msym);
|
||||||
}
|
}
|
||||||
return super.inst(inferred, types);
|
|
||||||
}};
|
}};
|
||||||
return mt2;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// check that actuals conform to inferred formals
|
// check that actuals conform to inferred formals
|
||||||
@ -506,6 +501,62 @@ public class Infer {
|
|||||||
}
|
}
|
||||||
//where
|
//where
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A delegated type representing a partially uninferred method type.
|
||||||
|
* The return type of a partially uninferred method type is a ForAll
|
||||||
|
* type - when the return type is instantiated (see Infer.instantiateExpr)
|
||||||
|
* the underlying method type is also updated.
|
||||||
|
*/
|
||||||
|
static abstract class UninferredMethodType extends DelegatedType {
|
||||||
|
|
||||||
|
final List<Type> tvars;
|
||||||
|
|
||||||
|
public UninferredMethodType(MethodType mtype, List<Type> tvars) {
|
||||||
|
super(METHOD, new MethodType(mtype.argtypes, null, mtype.thrown, mtype.tsym));
|
||||||
|
this.tvars = tvars;
|
||||||
|
asMethodType().restype = new UninferredReturnType(tvars, mtype.restype);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MethodType asMethodType() {
|
||||||
|
return qtype.asMethodType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type map(Mapping f) {
|
||||||
|
return qtype.map(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void instantiateReturnType(Type restype, List<Type> inferred, Types types) throws NoInstanceException {
|
||||||
|
//update method type with newly inferred type-arguments
|
||||||
|
qtype = new MethodType(types.subst(getParameterTypes(), tvars, inferred),
|
||||||
|
restype,
|
||||||
|
types.subst(UninferredMethodType.this.getThrownTypes(), tvars, inferred),
|
||||||
|
UninferredMethodType.this.qtype.tsym);
|
||||||
|
check(inferred, types);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract void check(List<Type> inferred, Types types) throws NoInstanceException;
|
||||||
|
|
||||||
|
abstract List<Type> getConstraints(TypeVar tv, ConstraintKind ck);
|
||||||
|
|
||||||
|
class UninferredReturnType extends ForAll {
|
||||||
|
public UninferredReturnType(List<Type> tvars, Type restype) {
|
||||||
|
super(tvars, restype);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Type inst(List<Type> actuals, Types types) {
|
||||||
|
Type newRestype = super.inst(actuals, types);
|
||||||
|
instantiateReturnType(newRestype, actuals, types);
|
||||||
|
return newRestype;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) {
|
||||||
|
return UninferredMethodType.this.getConstraints(tv, ck);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals,
|
private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals,
|
||||||
boolean allowBoxing, boolean useVarargs, Warner warn) {
|
boolean allowBoxing, boolean useVarargs, Warner warn) {
|
||||||
try {
|
try {
|
||||||
@ -518,25 +569,25 @@ public class Infer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Try to instantiate argument type `that' to given type `to'.
|
/** Try to instantiate argument type `that' to given type `to'.
|
||||||
* If this fails, try to insantiate `that' to `to' where
|
* If this fails, try to insantiate `that' to `to' where
|
||||||
* every occurrence of a type variable in `tvars' is replaced
|
* every occurrence of a type variable in `tvars' is replaced
|
||||||
* by an unknown type.
|
* by an unknown type.
|
||||||
*/
|
*/
|
||||||
private Type instantiateArg(ForAll that,
|
private Type instantiateArg(ForAll that,
|
||||||
Type to,
|
Type to,
|
||||||
List<Type> tvars,
|
List<Type> tvars,
|
||||||
Warner warn) throws InferenceException {
|
Warner warn) throws InferenceException {
|
||||||
List<Type> targs;
|
List<Type> targs;
|
||||||
try {
|
try {
|
||||||
return instantiateExpr(that, to, warn);
|
return instantiateExpr(that, to, warn);
|
||||||
} catch (NoInstanceException ex) {
|
} catch (NoInstanceException ex) {
|
||||||
Type to1 = to;
|
Type to1 = to;
|
||||||
for (List<Type> l = tvars; l.nonEmpty(); l = l.tail)
|
for (List<Type> l = tvars; l.nonEmpty(); l = l.tail)
|
||||||
to1 = types.subst(to1, List.of(l.head), List.of(syms.unknownType));
|
to1 = types.subst(to1, List.of(l.head), List.of(syms.unknownType));
|
||||||
return instantiateExpr(that, to1, warn);
|
return instantiateExpr(that, to1, warn);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** check that type parameters are within their bounds.
|
/** check that type parameters are within their bounds.
|
||||||
*/
|
*/
|
||||||
@ -616,4 +667,4 @@ public class Infer {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
131
langtools/test/tools/javac/generics/7015430/T7015430.java
Normal file
131
langtools/test/tools/javac/generics/7015430/T7015430.java
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @bug 7015430
|
||||||
|
*
|
||||||
|
* @summary Incorrect thrown type determined for unchecked invocations
|
||||||
|
* @author Daniel Smith
|
||||||
|
* @compile/fail/ref=T7015430.out -Xlint:unchecked -XDrawDiagnostics T7015430.java
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
class T7015430 {
|
||||||
|
static <E extends Exception> Iterable<E> empty(Iterable<E> arg) throws E {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
<E extends Exception> T7015430(Iterable<E> arg) throws E { }
|
||||||
|
|
||||||
|
static <E extends Exception> Iterable<E> empty2(Iterable x) throws E {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Foo<X extends Exception> {
|
||||||
|
Foo() throws X {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method invocation, no unchecked
|
||||||
|
* inferred: RuntimeException - should pass
|
||||||
|
*/
|
||||||
|
void m1() {
|
||||||
|
Iterable<RuntimeException> i = java.util.Collections.emptyList();
|
||||||
|
empty(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method invocation, unchecked, inferred arguments
|
||||||
|
* inferred: Exception - should fail
|
||||||
|
*/
|
||||||
|
void m2() {
|
||||||
|
Iterable i = java.util.Collections.EMPTY_LIST;
|
||||||
|
empty(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method invocation, unchecked, explicit arguments
|
||||||
|
* inferred: RuntimeException - should pass
|
||||||
|
*/
|
||||||
|
void m3() {
|
||||||
|
Iterable i = java.util.Collections.EMPTY_LIST;
|
||||||
|
T7015430.<RuntimeException>empty(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor invocation, no unchecked
|
||||||
|
* inferred: RuntimeException - should pass
|
||||||
|
*/
|
||||||
|
void m4() {
|
||||||
|
Iterable<RuntimeException> i = java.util.Collections.emptyList();
|
||||||
|
new T7015430(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor invocation, unchecked, inferred arguments
|
||||||
|
* inferred: Exception - should fail
|
||||||
|
*/
|
||||||
|
void m5() {
|
||||||
|
Iterable i = java.util.Collections.EMPTY_LIST;
|
||||||
|
new T7015430(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor invocation, unchecked, explicit arguments
|
||||||
|
* inferred: RuntimeException - should pass
|
||||||
|
*/
|
||||||
|
void m6() {
|
||||||
|
Iterable i = java.util.Collections.EMPTY_LIST;
|
||||||
|
new <RuntimeException>T7015430(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method invocation, no unchecked, inferred arguments
|
||||||
|
* inferred: RuntimeException - should pass
|
||||||
|
*/
|
||||||
|
void m7() {
|
||||||
|
Iterable i = java.util.Collections.EMPTY_LIST;
|
||||||
|
Iterable<RuntimeException> e = empty2(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method invocation, no unchecked, inferred arguments
|
||||||
|
* inferred: Exception - should fail
|
||||||
|
*/
|
||||||
|
void m8() {
|
||||||
|
Iterable i = java.util.Collections.EMPTY_LIST;
|
||||||
|
empty2(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor invocation, unchecked, explicit arguments
|
||||||
|
* inferred: RuntimeException - should pass
|
||||||
|
*/
|
||||||
|
void m9() {
|
||||||
|
Iterable i = java.util.Collections.EMPTY_LIST;
|
||||||
|
new <RuntimeException> T7015430(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor invocation, unchecked, inferred arguments
|
||||||
|
* inferred: Exception - should fail
|
||||||
|
*/
|
||||||
|
void m10() {
|
||||||
|
Iterable i = java.util.Collections.EMPTY_LIST;
|
||||||
|
new T7015430(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor invocation, no unchecked, inferred arguments (diamond)
|
||||||
|
* inferred: RuntimeException - should pass
|
||||||
|
*/
|
||||||
|
void m11() {
|
||||||
|
Foo<RuntimeException> o = new Foo<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor invocation, no unchecked, inferred arguments (diamond)
|
||||||
|
* inferred: Exception - should fail
|
||||||
|
*/
|
||||||
|
void m12() {
|
||||||
|
new Foo<>();
|
||||||
|
}
|
||||||
|
}
|
19
langtools/test/tools/javac/generics/7015430/T7015430.out
Normal file
19
langtools/test/tools/javac/generics/7015430/T7015430.out
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
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: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: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: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: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: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: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:95:15: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
|
||||||
|
T7015430.java:113:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
|
||||||
|
T7015430.java:129:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
|
||||||
|
5 errors
|
||||||
|
12 warnings
|
Loading…
x
Reference in New Issue
Block a user