changeset 658:1805864c6a0f

Bug fixes: *) javac complains about missing overrides when defender methods are available *) lambda return type should not be inferred to 'void' if lambda expression cannot return normally *) build problem when boot.java.home points to a JDK 7 build
author mcimadamore
date Thu, 26 Aug 2010 12:14:11 +0100
parents 0ea4e43f5fc4
children db1d811040a5
files src/share/classes/com/sun/runtime/ProxyHelper.java src/share/classes/com/sun/tools/javac/code/Symbol.java src/share/classes/com/sun/tools/javac/code/Types.java src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/Check.java src/share/classes/com/sun/tools/javac/comp/Flow.java src/share/classes/com/sun/tools/javac/resources/compiler.properties test/tools/javac/defender/Neg01.java test/tools/javac/defender/Neg01.out test/tools/javac/defender/Pos02.java test/tools/javac/defender/Pos03.java test/tools/javac/defender/Pos04.java test/tools/javac/diags/examples.not-yet.txt test/tools/javac/lambda/ExceptionTransparency03.java test/tools/javac/lambda/ExceptionTransparency03.out
diffstat 15 files changed, 227 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/runtime/ProxyHelper.java	Wed Aug 25 11:24:15 2010 +0100
+++ b/src/share/classes/com/sun/runtime/ProxyHelper.java	Thu Aug 26 12:14:11 2010 +0100
@@ -63,11 +63,14 @@
             }
 
             Object dispatchObjectMethod(Method method, Object... args) throws Throwable {
-                switch(method.getName()) {
-                    case "hashCode": return hashCode();
-                    case "equals": return equals(args[0]);
-                    case "toString": return toString();
-                    default: throw new AssertionError("Bad Object method " + method);
+                if (method.getName().equals("hashCode")) {
+                    return hashCode();
+                } else if (method.getName().equals("equals")) {
+                    return equals(args[0]);
+                } else if (method.getName().equals("toString")) {
+                    return toString();
+                } else {
+                    throw new AssertionError("Bad Object method " + method);
                 }
             }
         });
--- a/src/share/classes/com/sun/tools/javac/code/Symbol.java	Wed Aug 25 11:24:15 2010 +0100
+++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java	Thu Aug 26 12:14:11 2010 +0100
@@ -1180,7 +1180,8 @@
             }
 
             // check for an inherited implementation
-            if ((flags() & ABSTRACT) != 0 ||
+            if (((flags() & ABSTRACT) != 0 &&
+                    (flags() & DEFENDER) == 0) ||
                 (other.flags() & ABSTRACT) == 0 ||
                 !other.isOverridableIn(origin) ||
                 !this.isMemberOf(origin, types))
--- a/src/share/classes/com/sun/tools/javac/code/Types.java	Wed Aug 25 11:24:15 2010 +0100
+++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Aug 26 12:14:11 2010 +0100
@@ -2541,26 +2541,44 @@
         }
         MethodSymbol impl = cache.get(origin);
         if (impl == null) {
-            for (Type t = origin.type; t.tag == CLASS || t.tag == TYPEVAR; t = types.supertype(t)) {
-                while (t.tag == TYPEVAR)
-                    t = t.getUpperBound();
-                TypeSymbol c = t.tsym;
-                for (Scope.Entry e = c.members().lookup(ms.name);
-                     e.scope != null;
-                     e = e.next()) {
-                    if (e.sym.kind == Kinds.MTH) {
-                        MethodSymbol m = (MethodSymbol) e.sym;
-                        if (m.overrides(ms, origin, types, checkResult) &&
-                            (m.flags() & SYNTHETIC) == 0) {
-                            impl = m;
-                            cache.put(origin, m);
-                            return impl;
-                        }
+            impl = implementation(ms, origin, types, checkResult, cache, false);
+            if (impl == null &&
+                source.allowDefenderMethods()) {
+                impl = implementation(ms, origin, types, checkResult, cache, true);
+            }
+        }
+        return impl;
+    }
+
+    private MethodSymbol implementation(MethodSymbol ms, TypeSymbol origin, Types types, boolean checkResult,
+            Map<TypeSymbol, MethodSymbol> cache, boolean defenderAllowed) {
+        boolean isInterface = origin.isInterface();
+        for (Type t = origin.type; t.tag == CLASS || t.tag == TYPEVAR; t = types.supertype(t)) {
+            while (t.tag == TYPEVAR)
+                t = t.getUpperBound();
+            TypeSymbol c = t.tsym;
+            for (Scope.Entry e = c.members().lookup(ms.name);
+                 e.scope != null;
+                 e = e.next()) {
+                if (e.sym.kind == Kinds.MTH) {
+                    MethodSymbol m = (MethodSymbol) e.sym;
+                    if (m.overrides(ms, origin, types, checkResult) &&
+                        (m.flags() & SYNTHETIC) == 0 &&
+                        (!defenderAllowed || !isInterface || (m.flags() & DEFENDER) != 0)) {
+                        cache.put(origin, m);
+                        return m;
                     }
                 }
             }
+            if (defenderAllowed) {
+                for (Type t2 : interfaces(t)) {
+                    MethodSymbol impl = implementation(ms, t2.tsym, types, checkResult, cache, defenderAllowed);
+                    if (impl != null)
+                        return impl;
+                }
+            }
         }
-        return impl;
+        return null;
     }
 
     /**
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Aug 25 11:24:15 2010 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Aug 26 12:14:11 2010 +0100
@@ -2236,7 +2236,7 @@
             JCBlock body = (JCBlock)that.body;
             attribStats(body.stats, localEnv);
             resType = localEnv.info.scope.owner.type.getReturnType();
-            if (resType == null || resType == Type.noType) {
+            if (resType == null) {
                 //this happens if the body contains an expression statement
                 resType = syms.voidType;
             }
--- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Wed Aug 25 11:24:15 2010 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Thu Aug 26 12:14:11 2010 +0100
@@ -96,6 +96,7 @@
         allowGenerics = source.allowGenerics();
         allowAnnotations = source.allowAnnotations();
         allowCovariantReturns = source.allowCovariantReturns();
+        allowDefenderMethods = source.allowDefenderMethods();
         complexInference = options.get("-complexinference") != null;
         skipAnnotations = options.get("skipAnnotations") != null;
         warnOnSyntheticConflicts = options.get("warnOnSyntheticConflicts") != null;
@@ -132,6 +133,10 @@
      */
     boolean allowCovariantReturns;
 
+    /** Switch: defender methods enabled?
+     */
+    boolean allowDefenderMethods;
+
     /** Switch: -complexinference option set?
      */
     boolean complexInference;
@@ -1616,11 +1621,11 @@
                                             Type t1,
                                             Type t2,
                                             Type site) {
-        Symbol sym = firstIncompatibility(t1, t2, site);
-        if (sym != null) {
-            log.error(pos, "types.incompatible.diff.ret",
-                      t1, t2, sym.name +
-                      "(" + types.memberType(t2, sym).getParameterTypes() + ")");
+        CompatibilityResult res = firstIncompatibility(t1, t2, site);
+        if (res.isErroneous()) {
+            log.error(pos, res.errKey,
+                      t1, t2, res.sym.name +
+                      "(" + types.memberType(t2, res.sym).getParameterTypes() + ")");
             return false;
         }
         return true;
@@ -1634,7 +1639,21 @@
      *  @param site   The most derived type.
      *  @returns symbol from t2 that conflicts with one in t1.
      */
-    private Symbol firstIncompatibility(Type t1, Type t2, Type site) {
+    static class CompatibilityResult {
+        CompatibilityResult(Symbol sym, String errKey) {
+            this.sym = sym;
+            this.errKey = errKey;
+        }
+        CompatibilityResult() {
+            this(null, null);
+        }
+        boolean isErroneous() {
+            return sym != null;
+        }
+        Symbol sym;
+        String errKey;
+    }
+    private CompatibilityResult firstIncompatibility(Type t1, Type t2, Type site) {
         Map<TypeSymbol,Type> interfaces1 = new HashMap<TypeSymbol,Type>();
         closure(t1, interfaces1);
         Map<TypeSymbol,Type> interfaces2;
@@ -1645,11 +1664,11 @@
 
         for (Type t3 : interfaces1.values()) {
             for (Type t4 : interfaces2.values()) {
-                Symbol s = firstDirectIncompatibility(t3, t4, site);
-                if (s != null) return s;
+                CompatibilityResult res = firstDirectIncompatibility(t3, t4, site);
+                if (res.isErroneous()) return res;
             }
         }
-        return null;
+        return new CompatibilityResult();
     }
 
     /** Compute all the supertypes of t, indexed by type symbol. */
@@ -1674,7 +1693,7 @@
     }
 
     /** Return the first method in t2 that conflicts with a method from t1. */
-    private Symbol firstDirectIncompatibility(Type t1, Type t2, Type site) {
+    private CompatibilityResult firstDirectIncompatibility(Type t1, Type t2, Type site) {
         for (Scope.Entry e1 = t1.tsym.members().elems; e1 != null; e1 = e1.sibling) {
             Symbol s1 = e1.sym;
             Type st1 = null;
@@ -1698,11 +1717,18 @@
                         (types.covariantReturnType(rt1, rt2, Warner.noWarnings) ||
                          types.covariantReturnType(rt2, rt1, Warner.noWarnings)) ||
                          checkCommonOverriderIn(s1,s2,site);
-                    if (!compat) return s2;
+                    String errKey = "types.incompatible.diff.ret";
+                    if (compat && allowDefenderMethods) {
+                        compat &= ((s1.flags() & DEFENDER) != (s2.flags() & DEFENDER)) ||
+                                (((MethodSymbol)s1).defaultImpl ==
+                                ((MethodSymbol)s2).defaultImpl);
+                        errKey = "types.incompatible.diff.default";
+                    }
+                    if (!compat) return new CompatibilityResult(s2, errKey);
                 }
             }
         }
-        return null;
+        return new CompatibilityResult();
     }
     //WHERE
     boolean checkCommonOverriderIn(Symbol s1, Symbol s2, Type site) {
--- a/src/share/classes/com/sun/tools/javac/comp/Flow.java	Wed Aug 25 11:24:15 2010 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Flow.java	Thu Aug 26 12:14:11 2010 +0100
@@ -1336,6 +1336,8 @@
             }
             if (tree.type.getThrownTypes() == null) {
                 tree.type.setThrown(thrown);
+                if (alive && tree.type.getReturnType() == Type.noType)
+                    ((FunctionType)tree.type).restype = syms.voidType;
             }
         }
         finally {
--- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Wed Aug 25 11:24:15 2010 +0100
+++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu Aug 26 12:14:11 2010 +0100
@@ -512,6 +512,8 @@
     type variable {0} occurs more than once in type of {1}; cannot be left uninstantiated
 compiler.err.types.incompatible.diff.ret=\
     types {0} and {1} are incompatible; both define {2}, but with unrelated return types
+compiler.err.types.incompatible.diff.default=\
+    types {0} and {1} are incompatible; both define {2}, but with unrelated default implementations
 
 compiler.err.unclosed.bytecode.ident=\
     unclosed bytecode identifier
--- a/test/tools/javac/defender/Neg01.java	Wed Aug 25 11:24:15 2010 +0100
+++ b/test/tools/javac/defender/Neg01.java	Thu Aug 26 12:14:11 2010 +0100
@@ -39,8 +39,4 @@
 
     static int m1(IA a) { return 0; }
     static int m2(IB b) { return 0; }
-
-    static void test() {
-        new AB().m(); //ambiguous
-    }
 }
--- a/test/tools/javac/defender/Neg01.out	Wed Aug 25 11:24:15 2010 +0100
+++ b/test/tools/javac/defender/Neg01.out	Thu Aug 26 12:14:11 2010 +0100
@@ -1,2 +1,2 @@
-Neg01.java:44:17: compiler.err.ref.ambiguous: m, kindname.method, m(), Neg01.IB, kindname.method, m(), Neg01.IA
+Neg01.java:38:12: compiler.err.types.incompatible.diff.default: Neg01.IB, Neg01.IA, m()
 1 error
--- a/test/tools/javac/defender/Pos02.java	Wed Aug 25 11:24:15 2010 +0100
+++ b/test/tools/javac/defender/Pos02.java	Thu Aug 26 12:14:11 2010 +0100
@@ -36,6 +36,7 @@
     static class B implements IB {}
 
     static class AB implements IA, IB {
+        public int m() { return 0; }
         void test() {
             IA.this.m();
             IA.super.m();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/defender/Pos03.java	Thu Aug 26 12:14:11 2010 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010, 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
+ * @summary test for overriding with defender method
+ * @author  Maurizio Cimadamore
+ * @compile Pos03.java
+ */
+
+class Pos03 {
+    interface IA { extension int m() default Pos03.m; }
+    interface IB { int m(); }
+
+    static class AB implements IA, IB {
+        void test() {
+            IA.this.m();
+            IA.super.m();
+        }
+    }
+
+    static int m(IA a) { return 0; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/defender/Pos04.java	Thu Aug 26 12:14:11 2010 +0100
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010, 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
+ * @summary test for overriding with defender method
+ * @author  Maurizio Cimadamore
+ * @compile Pos04.java
+ */
+
+class Pos04 {
+    interface A { extension int m() default Pos04.m; }
+    static abstract class B { public int m() { return 0; } }
+
+    static class C extends B implements A {
+        void test() {
+            A.this.m();
+            A.super.m();
+        }
+    }
+
+    static int m(A a) { return 0; }
+}
--- a/test/tools/javac/diags/examples.not-yet.txt	Wed Aug 25 11:24:15 2010 +0100
+++ b/test/tools/javac/diags/examples.not-yet.txt	Thu Aug 26 12:14:11 2010 +0100
@@ -130,6 +130,7 @@
 compiler.err.throws.typaram.not.allowed.here                                     #LAMBDA
 compiler.err.unexpected.lambda                                                   #LAMBDA
 compiler.err.unexpected.meth.reference                                           #LAMBDA
+compiler.err.types.incompatible.diff.default                                     #LAMBDA
 compiler.misc.disjunctive.type                                                   #LAMBDA
 compiler.misc.encl.instance.for.lambda.conv.target.must.be.in.scope              #LAMBDA
 compiler.misc.incompatible.target.in.lambda.conv                                 #LAMBDA
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/ExceptionTransparency03.java	Thu Aug 26 12:14:11 2010 +0100
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2010, 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
+ * @summary check that lambda return type is not inferred to 'void' if lambda expr cannot return normally
+ * @author  Maurizio Cimadamore
+ * @compile/fail/ref=ExceptionTransparency03.out -XDrawDiagnostics ExceptionTransparency03.java
+ */
+
+import java.util.*;
+
+class ExceptionTransparency03 {
+    interface Func<R, A1, throws E> { public R apply( A1 a1 ) throws E; }
+
+    interface SortableList<T extends Comparable<? super T>> extends List<T> {
+      <throws E> void forEach( Func<T, T, E> method ) throws E;
+    }
+
+    static abstract class IntSortableList extends AbstractList<Integer> implements SortableList<Integer> { }
+
+    void test(IntSortableList isl) {
+        isl.forEach( Func<Integer,Integer, Exception> #( i ) { throw new Exception(); } );
+        isl.forEach(  #( i ) { throw new Exception(); } );
+        isl.<Exception>forEach( #( i ) { throw new Exception(); } );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/ExceptionTransparency03.out	Thu Aug 26 12:14:11 2010 +0100
@@ -0,0 +1,4 @@
+ExceptionTransparency03.java:43:20: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
+ExceptionTransparency03.java:44:20: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
+ExceptionTransparency03.java:45:31: compiler.err.unreported.exception.need.to.catch.or.throw: java.lang.Exception
+3 errors