7015430: Incorrect thrown type determined for unchecked invocations

Mon, 28 Feb 2011 11:48:53 +0000

author
mcimadamore
date
Mon, 28 Feb 2011 11:48:53 +0000
changeset 895
9286a5d1fae3
parent 894
23b64ad3eec8
child 896
9f9df9684cfc

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

src/share/classes/com/sun/tools/javac/comp/Attr.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/comp/Infer.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/7015430/T7015430.java file | annotate | diff | comparison | revisions
test/tools/javac/generics/7015430/T7015430.out file | annotate | diff | comparison | revisions
     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

mercurial