8012242: Lambda compatibility and checked exceptions
authormcimadamore
Wed, 17 Jul 2013 14:04:01 +0100
changeset 18909 8f9fc5d876e4
parent 18908 f76cab33bee3
child 18910 c967bfda9283
8012242: Lambda compatibility and checked exceptions Summary: Inference variables in 'throws' clause with no constraints should be inferred as RuntimeException Reviewed-by: jjg, vromero
langtools/src/share/classes/com/sun/tools/javac/code/Flags.java
langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java
langtools/test/tools/javac/generics/6723444/T6723444.java
langtools/test/tools/javac/generics/6723444/T6723444.out
langtools/test/tools/javac/generics/6723444/T6723444_1.out
langtools/test/tools/javac/generics/6723444/T6723444_2.out
langtools/test/tools/javac/generics/7015430/T7015430.java
langtools/test/tools/javac/generics/7015430/T7015430.out
langtools/test/tools/javac/generics/7015430/T7015430_1.out
langtools/test/tools/javac/generics/7015430/T7015430_2.out
langtools/test/tools/javac/lambda/TargetType63.java
langtools/test/tools/javac/lambda/TargetType63.out
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java	Fri Jul 12 13:11:12 2013 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java	Wed Jul 17 14:04:01 2013 +0100
@@ -261,6 +261,11 @@
      */
     public static final long SIGNATURE_POLYMORPHIC = 1L<<46;
 
+    /**
+     * Flag that marks inference variables used in a 'throws' clause
+     */
+    public static final long THROWS = 1L<<47;
+
     /** Modifier masks.
      */
     public static final int
@@ -365,7 +370,9 @@
         CLASH(Flags.CLASH),
         AUXILIARY(Flags.AUXILIARY),
         NOT_IN_PROFILE(Flags.NOT_IN_PROFILE),
-        BAD_OVERRIDE(Flags.BAD_OVERRIDE);
+        BAD_OVERRIDE(Flags.BAD_OVERRIDE),
+        SIGNATURE_POLYMORPHIC(Flags.SIGNATURE_POLYMORPHIC),
+        THROWS(Flags.THROWS);
 
         Flag(long flag) {
             this.value = flag;
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Fri Jul 12 13:11:12 2013 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Wed Jul 17 14:04:01 2013 +0100
@@ -968,6 +968,39 @@
             }
         },
         /**
+         * Infer uninstantiated/unbound inference variables occurring in 'throws'
+         * clause as RuntimeException
+         */
+        THROWS(InferenceBound.UPPER) {
+            @Override
+            public boolean accepts(UndetVar t, InferenceContext inferenceContext) {
+                if ((t.qtype.tsym.flags() & Flags.THROWS) == 0) {
+                    //not a throws undet var
+                    return false;
+                }
+                if (t.getBounds(InferenceBound.EQ, InferenceBound.LOWER, InferenceBound.UPPER)
+                            .diff(t.getDeclaredBounds()).nonEmpty()) {
+                    //not an unbounded undet var
+                    return false;
+                }
+                Infer infer = inferenceContext.infer();
+                for (Type db : t.getDeclaredBounds()) {
+                    if (t.isInterface()) continue;
+                    if (infer.types.asSuper(infer.syms.runtimeExceptionType, db.tsym) != null) {
+                        //declared bound is a supertype of RuntimeException
+                        return true;
+                    }
+                }
+                //declared bound is more specific then RuntimeException - give up
+                return false;
+            }
+
+            @Override
+            Type solve(UndetVar uv, InferenceContext inferenceContext) {
+                return inferenceContext.infer().syms.runtimeExceptionType;
+            }
+        },
+        /**
          * Instantiate an inference variables using its (ground) upper bounds. Such
          * bounds are merged together using glb().
          */
@@ -1056,7 +1089,7 @@
 
         EQ(EnumSet.of(InferenceStep.EQ)),
         EQ_LOWER(EnumSet.of(InferenceStep.EQ, InferenceStep.LOWER)),
-        EQ_LOWER_UPPER(EnumSet.of(InferenceStep.EQ, InferenceStep.LOWER, InferenceStep.UPPER));
+        EQ_LOWER_THROWS_UPPER(EnumSet.of(InferenceStep.EQ, InferenceStep.LOWER, InferenceStep.THROWS, InferenceStep.UPPER));
 
         final EnumSet<InferenceStep> steps;
 
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Fri Jul 12 13:11:12 2013 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Wed Jul 17 14:04:01 2013 +0100
@@ -358,7 +358,8 @@
      *  @param thrown      The method's thrown exceptions.
      *  @param env             The method's (local) environment.
      */
-    Type signature(List<JCTypeParameter> typarams,
+    Type signature(MethodSymbol msym,
+                   List<JCTypeParameter> typarams,
                    List<JCVariableDecl> params,
                    JCTree res,
                    JCVariableDecl recvparam,
@@ -392,8 +393,12 @@
         ListBuffer<Type> thrownbuf = new ListBuffer<Type>();
         for (List<JCExpression> l = thrown; l.nonEmpty(); l = l.tail) {
             Type exc = attr.attribType(l.head, env);
-            if (!exc.hasTag(TYPEVAR))
+            if (!exc.hasTag(TYPEVAR)) {
                 exc = chk.checkClassType(l.head.pos(), exc);
+            } else if (exc.tsym.owner == msym) {
+                //mark inference variables in 'throws' clause
+                exc.tsym.flags_field |= THROWS;
+            }
             thrownbuf.append(exc);
         }
         MethodType mtype = new MethodType(argbuf.toList(),
@@ -557,7 +562,7 @@
                 chk.setDeferredLintHandler(deferredLintHandler.setPos(tree.pos()));
         try {
             // Compute the method type
-            m.type = signature(tree.typarams, tree.params,
+            m.type = signature(m, tree.typarams, tree.params,
                                tree.restype, tree.recvparam,
                                tree.thrown,
                                localEnv);
--- a/langtools/test/tools/javac/generics/6723444/T6723444.java	Fri Jul 12 13:11:12 2013 -0700
+++ b/langtools/test/tools/javac/generics/6723444/T6723444.java	Wed Jul 17 14:04:01 2013 +0100
@@ -4,7 +4,8 @@
  *
  * @summary javac fails to substitute type variables into a constructor's throws clause
  * @author Mark Mahieu
- * @compile/fail/ref=T6723444.out -XDrawDiagnostics T6723444.java
+ * @compile/fail/ref=T6723444_1.out -Xlint:-options -source 7 -XDrawDiagnostics T6723444.java
+ * @compile/fail/ref=T6723444_2.out -XDrawDiagnostics T6723444.java
  *
  */
 public class T6723444 {
--- a/langtools/test/tools/javac/generics/6723444/T6723444.out	Fri Jul 12 13:11:12 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-T6723444.java:42:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
-T6723444.java:43:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
-T6723444.java:45:32: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
-T6723444.java:46:17: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
-T6723444.java:48:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
-T6723444.java:49:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
-T6723444.java:50:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
-T6723444.java:51:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
-T6723444.java:52:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
-T6723444.java:53:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
-T6723444.java:54:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
-T6723444.java:55:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
-12 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/6723444/T6723444_1.out	Wed Jul 17 14:04:01 2013 +0100
@@ -0,0 +1,13 @@
+T6723444.java:43:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:44:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:46:32: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:47:17: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:49:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:50:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:51:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:52:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:53:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:54:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:55:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:56:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+12 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/6723444/T6723444_2.out	Wed Jul 17 14:04:01 2013 +0100
@@ -0,0 +1,11 @@
+T6723444.java:46:32: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:47:17: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:49:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:50:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:51:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:52:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:53:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:54:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:55:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+T6723444.java:56:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Throwable
+10 errors
--- a/langtools/test/tools/javac/generics/7015430/T7015430.java	Fri Jul 12 13:11:12 2013 -0700
+++ b/langtools/test/tools/javac/generics/7015430/T7015430.java	Wed Jul 17 14:04:01 2013 +0100
@@ -4,7 +4,8 @@
  *
  * @summary  Incorrect thrown type determined for unchecked invocations
  * @author Daniel Smith
- * @compile/fail/ref=T7015430.out -Xlint:unchecked -XDrawDiagnostics T7015430.java
+ * @compile/fail/ref=T7015430_1.out -source 7 -Xlint:-options,unchecked -XDrawDiagnostics T7015430.java
+ * @compile/fail/ref=T7015430_2.out -Xlint:unchecked -XDrawDiagnostics T7015430.java
  *
  */
 
--- a/langtools/test/tools/javac/generics/7015430/T7015430.out	Fri Jul 12 13:11:12 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-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:15: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.Exception>
-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:42: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
-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:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.Exception>
-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:40: 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:41: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
-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:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<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: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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/7015430/T7015430_1.out	Wed Jul 17 14:04:01 2013 +0100
@@ -0,0 +1,19 @@
+T7015430.java:42:14: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
+T7015430.java:42:15: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<E>
+T7015430.java:51:41: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
+T7015430.java:51:42: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
+T7015430.java:69:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
+T7015430.java:69:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<E>
+T7015430.java:78:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
+T7015430.java:78:40: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
+T7015430.java:105:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
+T7015430.java:105:41: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
+T7015430.java:114:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
+T7015430.java:114:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<E>
+T7015430.java:42:14: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
+T7015430.java:69:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
+T7015430.java:96:15: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
+T7015430.java:114:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
+T7015430.java:130:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
+5 errors
+12 warnings
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/7015430/T7015430_2.out	Wed Jul 17 14:04:01 2013 +0100
@@ -0,0 +1,15 @@
+T7015430.java:42:14: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
+T7015430.java:42:15: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
+T7015430.java:51:41: compiler.warn.unchecked.meth.invocation.applied: kindname.method, empty, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
+T7015430.java:51:42: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
+T7015430.java:69:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
+T7015430.java:69:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
+T7015430.java:78:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
+T7015430.java:78:40: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
+T7015430.java:105:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
+T7015430.java:105:41: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
+T7015430.java:114:9: compiler.warn.unchecked.meth.invocation.applied: kindname.constructor, <init>, java.lang.Iterable<E>, java.lang.Iterable, kindname.class, T7015430
+T7015430.java:114:22: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), java.lang.Iterable, java.lang.Iterable<java.lang.RuntimeException>
+T7015430.java:130:9: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
+1 error
+12 warnings
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/TargetType63.java	Wed Jul 17 14:04:01 2013 +0100
@@ -0,0 +1,40 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary smoke test for inference of throws type variables
+ * @compile/fail/ref=TargetType63.out -XDrawDiagnostics TargetType63.java
+ */
+class TargetType63 {
+
+    interface F<T extends Throwable> {
+        void m() throws T;
+    }
+
+    void g1() { }
+    void g2() throws ClassNotFoundException { }
+    void g3() throws Exception { }
+
+    <Z extends Throwable> void m1(F<Z> fz) throws Z { }
+    <Z extends ClassNotFoundException> void m2(F<Z> fz) throws Z { }
+
+    void test1() {
+        m1(()->{ }); //ok (Z = RuntimeException)
+        m1(this::g1); //ok (Z = RuntimeException)
+    }
+
+    void test2() {
+        m2(()->{ }); //fail (Z = ClassNotFoundException)
+        m2(this::g1); //fail (Z = ClassNotFoundException)
+    }
+
+    void test3() {
+        m1(()->{ throw new ClassNotFoundException(); }); //fail (Z = ClassNotFoundException)
+        m1(this::g2); //fail (Z = ClassNotFoundException)
+        m2(()->{ throw new ClassNotFoundException(); }); //fail (Z = ClassNotFoundException)
+        m2(this::g2); //fail (Z = ClassNotFoundException)
+    }
+
+    void test4() {
+        m1(()->{ throw new Exception(); }); //fail (Z = Exception)
+        m1(this::g3); //fail (Z = Exception)
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/TargetType63.out	Wed Jul 17 14:04:01 2013 +0100
@@ -0,0 +1,9 @@
+TargetType63.java:25:11: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.ClassNotFoundException
+TargetType63.java:26:11: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.ClassNotFoundException
+TargetType63.java:30:11: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.ClassNotFoundException
+TargetType63.java:31:11: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.ClassNotFoundException
+TargetType63.java:32:11: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.ClassNotFoundException
+TargetType63.java:33:11: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.ClassNotFoundException
+TargetType63.java:37:11: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
+TargetType63.java:38:11: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
+8 errors