Mon, 28 Feb 2011 11:48:53 +0000
7015430: Incorrect thrown type determined for unchecked invocations
Summary: 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
1.1 --- a/src/share/classes/com/sun/tools/javac/comp/Attr.java Fri Feb 25 12:19:00 2011 -0800 1.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java Mon Feb 28 11:48:53 2011 +0000 1.3 @@ -2806,7 +2806,7 @@ 1.4 sym.location()); 1.5 owntype = new MethodType(owntype.getParameterTypes(), 1.6 types.erasure(owntype.getReturnType()), 1.7 - owntype.getThrownTypes(), 1.8 + types.erasure(owntype.getThrownTypes()), 1.9 syms.methodClass); 1.10 } 1.11 if (useVarargs) {
2.1 --- a/src/share/classes/com/sun/tools/javac/comp/Infer.java Fri Feb 25 12:19:00 2011 -0800 2.2 +++ b/src/share/classes/com/sun/tools/javac/comp/Infer.java Mon Feb 28 11:48:53 2011 +0000 2.3 @@ -465,10 +465,9 @@ 2.4 // quantify result type with them 2.5 final List<Type> inferredTypes = insttypes.toList(); 2.6 final List<Type> all_tvars = tvars; //this is the wrong tvars 2.7 - final MethodType mt2 = new MethodType(mt.argtypes, null, mt.thrown, syms.methodClass); 2.8 - mt2.restype = new ForAll(restvars.toList(), mt.restype) { 2.9 + return new UninferredMethodType(mt, restvars.toList()) { 2.10 @Override 2.11 - public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) { 2.12 + List<Type> getConstraints(TypeVar tv, ConstraintKind ck) { 2.13 for (Type t : restundet.toList()) { 2.14 UndetVar uv = (UndetVar)t; 2.15 if (uv.qtype == tv) { 2.16 @@ -481,21 +480,17 @@ 2.17 } 2.18 return List.nil(); 2.19 } 2.20 - 2.21 @Override 2.22 - public Type inst(List<Type> inferred, Types types) throws NoInstanceException { 2.23 - List<Type> formals = types.subst(mt2.argtypes, tvars, inferred); 2.24 + void check(List<Type> inferred, Types types) throws NoInstanceException { 2.25 // check that actuals conform to inferred formals 2.26 - checkArgumentsAcceptable(env, capturedArgs, formals, allowBoxing, useVarargs, warn); 2.27 + checkArgumentsAcceptable(env, capturedArgs, getParameterTypes(), allowBoxing, useVarargs, warn); 2.28 // check that inferred bounds conform to their bounds 2.29 checkWithinBounds(all_tvars, 2.30 types.subst(inferredTypes, tvars, inferred), warn); 2.31 if (useVarargs) { 2.32 - chk.checkVararg(env.tree.pos(), formals, msym); 2.33 + chk.checkVararg(env.tree.pos(), getParameterTypes(), msym); 2.34 } 2.35 - return super.inst(inferred, types); 2.36 }}; 2.37 - return mt2; 2.38 } 2.39 else { 2.40 // check that actuals conform to inferred formals 2.41 @@ -506,6 +501,62 @@ 2.42 } 2.43 //where 2.44 2.45 + /** 2.46 + * A delegated type representing a partially uninferred method type. 2.47 + * The return type of a partially uninferred method type is a ForAll 2.48 + * type - when the return type is instantiated (see Infer.instantiateExpr) 2.49 + * the underlying method type is also updated. 2.50 + */ 2.51 + static abstract class UninferredMethodType extends DelegatedType { 2.52 + 2.53 + final List<Type> tvars; 2.54 + 2.55 + public UninferredMethodType(MethodType mtype, List<Type> tvars) { 2.56 + super(METHOD, new MethodType(mtype.argtypes, null, mtype.thrown, mtype.tsym)); 2.57 + this.tvars = tvars; 2.58 + asMethodType().restype = new UninferredReturnType(tvars, mtype.restype); 2.59 + } 2.60 + 2.61 + @Override 2.62 + public MethodType asMethodType() { 2.63 + return qtype.asMethodType(); 2.64 + } 2.65 + 2.66 + @Override 2.67 + public Type map(Mapping f) { 2.68 + return qtype.map(f); 2.69 + } 2.70 + 2.71 + void instantiateReturnType(Type restype, List<Type> inferred, Types types) throws NoInstanceException { 2.72 + //update method type with newly inferred type-arguments 2.73 + qtype = new MethodType(types.subst(getParameterTypes(), tvars, inferred), 2.74 + restype, 2.75 + types.subst(UninferredMethodType.this.getThrownTypes(), tvars, inferred), 2.76 + UninferredMethodType.this.qtype.tsym); 2.77 + check(inferred, types); 2.78 + } 2.79 + 2.80 + abstract void check(List<Type> inferred, Types types) throws NoInstanceException; 2.81 + 2.82 + abstract List<Type> getConstraints(TypeVar tv, ConstraintKind ck); 2.83 + 2.84 + class UninferredReturnType extends ForAll { 2.85 + public UninferredReturnType(List<Type> tvars, Type restype) { 2.86 + super(tvars, restype); 2.87 + } 2.88 + @Override 2.89 + public Type inst(List<Type> actuals, Types types) { 2.90 + Type newRestype = super.inst(actuals, types); 2.91 + instantiateReturnType(newRestype, actuals, types); 2.92 + return newRestype; 2.93 + } 2.94 + @Override 2.95 + public List<Type> getConstraints(TypeVar tv, ConstraintKind ck) { 2.96 + return UninferredMethodType.this.getConstraints(tv, ck); 2.97 + } 2.98 + } 2.99 + } 2.100 + 2.101 private void checkArgumentsAcceptable(Env<AttrContext> env, List<Type> actuals, List<Type> formals, 2.102 boolean allowBoxing, boolean useVarargs, Warner warn) { 2.103 try { 2.104 @@ -518,25 +569,25 @@ 2.105 } 2.106 } 2.107 2.108 - /** Try to instantiate argument type `that' to given type `to'. 2.109 - * If this fails, try to insantiate `that' to `to' where 2.110 - * every occurrence of a type variable in `tvars' is replaced 2.111 - * by an unknown type. 2.112 - */ 2.113 - private Type instantiateArg(ForAll that, 2.114 - Type to, 2.115 - List<Type> tvars, 2.116 - Warner warn) throws InferenceException { 2.117 - List<Type> targs; 2.118 - try { 2.119 - return instantiateExpr(that, to, warn); 2.120 - } catch (NoInstanceException ex) { 2.121 - Type to1 = to; 2.122 - for (List<Type> l = tvars; l.nonEmpty(); l = l.tail) 2.123 - to1 = types.subst(to1, List.of(l.head), List.of(syms.unknownType)); 2.124 - return instantiateExpr(that, to1, warn); 2.125 - } 2.126 + /** Try to instantiate argument type `that' to given type `to'. 2.127 + * If this fails, try to insantiate `that' to `to' where 2.128 + * every occurrence of a type variable in `tvars' is replaced 2.129 + * by an unknown type. 2.130 + */ 2.131 + private Type instantiateArg(ForAll that, 2.132 + Type to, 2.133 + List<Type> tvars, 2.134 + Warner warn) throws InferenceException { 2.135 + List<Type> targs; 2.136 + try { 2.137 + return instantiateExpr(that, to, warn); 2.138 + } catch (NoInstanceException ex) { 2.139 + Type to1 = to; 2.140 + for (List<Type> l = tvars; l.nonEmpty(); l = l.tail) 2.141 + to1 = types.subst(to1, List.of(l.head), List.of(syms.unknownType)); 2.142 + return instantiateExpr(that, to1, warn); 2.143 } 2.144 + } 2.145 2.146 /** check that type parameters are within their bounds. 2.147 */ 2.148 @@ -616,4 +667,4 @@ 2.149 return t; 2.150 } 2.151 }; 2.152 -} 2.153 + }
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/tools/javac/generics/7015430/T7015430.java Mon Feb 28 11:48:53 2011 +0000 3.3 @@ -0,0 +1,131 @@ 3.4 +/* 3.5 + * @test /nodynamiccopyright/ 3.6 + * @bug 7015430 3.7 + * 3.8 + * @summary Incorrect thrown type determined for unchecked invocations 3.9 + * @author Daniel Smith 3.10 + * @compile/fail/ref=T7015430.out -Xlint:unchecked -XDrawDiagnostics T7015430.java 3.11 + * 3.12 + */ 3.13 + 3.14 +class T7015430 { 3.15 + static <E extends Exception> Iterable<E> empty(Iterable<E> arg) throws E { 3.16 + return null; 3.17 + } 3.18 + 3.19 + <E extends Exception> T7015430(Iterable<E> arg) throws E { } 3.20 + 3.21 + static <E extends Exception> Iterable<E> empty2(Iterable x) throws E { 3.22 + return null; 3.23 + } 3.24 + 3.25 + static class Foo<X extends Exception> { 3.26 + Foo() throws X {} 3.27 + } 3.28 + 3.29 + /** 3.30 + * Method invocation, no unchecked 3.31 + * inferred: RuntimeException - should pass 3.32 + */ 3.33 + void m1() { 3.34 + Iterable<RuntimeException> i = java.util.Collections.emptyList(); 3.35 + empty(i); 3.36 + } 3.37 + 3.38 + /** 3.39 + * Method invocation, unchecked, inferred arguments 3.40 + * inferred: Exception - should fail 3.41 + */ 3.42 + void m2() { 3.43 + Iterable i = java.util.Collections.EMPTY_LIST; 3.44 + empty(i); 3.45 + } 3.46 + 3.47 + /** 3.48 + * Method invocation, unchecked, explicit arguments 3.49 + * inferred: RuntimeException - should pass 3.50 + */ 3.51 + void m3() { 3.52 + Iterable i = java.util.Collections.EMPTY_LIST; 3.53 + T7015430.<RuntimeException>empty(i); 3.54 + } 3.55 + 3.56 + /** 3.57 + * Constructor invocation, no unchecked 3.58 + * inferred: RuntimeException - should pass 3.59 + */ 3.60 + void m4() { 3.61 + Iterable<RuntimeException> i = java.util.Collections.emptyList(); 3.62 + new T7015430(i); 3.63 + } 3.64 + 3.65 + /** 3.66 + * Constructor invocation, unchecked, inferred arguments 3.67 + * inferred: Exception - should fail 3.68 + */ 3.69 + void m5() { 3.70 + Iterable i = java.util.Collections.EMPTY_LIST; 3.71 + new T7015430(i); 3.72 + } 3.73 + 3.74 + /** 3.75 + * Constructor invocation, unchecked, explicit arguments 3.76 + * inferred: RuntimeException - should pass 3.77 + */ 3.78 + void m6() { 3.79 + Iterable i = java.util.Collections.EMPTY_LIST; 3.80 + new <RuntimeException>T7015430(i); 3.81 + } 3.82 + 3.83 + /** 3.84 + * Method invocation, no unchecked, inferred arguments 3.85 + * inferred: RuntimeException - should pass 3.86 + */ 3.87 + void m7() { 3.88 + Iterable i = java.util.Collections.EMPTY_LIST; 3.89 + Iterable<RuntimeException> e = empty2(i); 3.90 + } 3.91 + 3.92 + /** 3.93 + * Method invocation, no unchecked, inferred arguments 3.94 + * inferred: Exception - should fail 3.95 + */ 3.96 + void m8() { 3.97 + Iterable i = java.util.Collections.EMPTY_LIST; 3.98 + empty2(i); 3.99 + } 3.100 + 3.101 + /** 3.102 + * Constructor invocation, unchecked, explicit arguments 3.103 + * inferred: RuntimeException - should pass 3.104 + */ 3.105 + void m9() { 3.106 + Iterable i = java.util.Collections.EMPTY_LIST; 3.107 + new <RuntimeException> T7015430(i); 3.108 + } 3.109 + 3.110 + /** 3.111 + * Constructor invocation, unchecked, inferred arguments 3.112 + * inferred: Exception - should fail 3.113 + */ 3.114 + void m10() { 3.115 + Iterable i = java.util.Collections.EMPTY_LIST; 3.116 + new T7015430(i); 3.117 + } 3.118 + 3.119 + /** 3.120 + * Constructor invocation, no unchecked, inferred arguments (diamond) 3.121 + * inferred: RuntimeException - should pass 3.122 + */ 3.123 + void m11() { 3.124 + Foo<RuntimeException> o = new Foo<>(); 3.125 + } 3.126 + 3.127 + /** 3.128 + * Constructor invocation, no unchecked, inferred arguments (diamond) 3.129 + * inferred: Exception - should fail 3.130 + */ 3.131 + void m12() { 3.132 + new Foo<>(); 3.133 + } 3.134 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/tools/javac/generics/7015430/T7015430.out Mon Feb 28 11:48:53 2011 +0000 4.3 @@ -0,0 +1,19 @@ 4.4 +T7015430.java:41:15: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<E> 4.5 +T7015430.java:41:14: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430 4.6 +T7015430.java:50:42: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException> 4.7 +T7015430.java:50:41: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430 4.8 +T7015430.java:68:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<E> 4.9 +T7015430.java:68:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430 4.10 +T7015430.java:77:40: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException> 4.11 +T7015430.java:77:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430 4.12 +T7015430.java:104:41: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException> 4.13 +T7015430.java:104:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430 4.14 +T7015430.java:113:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<E> 4.15 +T7015430.java:113:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430 4.16 +T7015430.java:41:14: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception 4.17 +T7015430.java:68:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception 4.18 +T7015430.java:95:15: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception 4.19 +T7015430.java:113:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception 4.20 +T7015430.java:129:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception 4.21 +5 errors 4.22 +12 warnings