changeset 1592:dc6dec36396b

Bug fixes: *) Spurious functional interface conversion error when target type inherits default methods (part two) *) target-type of lambda/method reference should be well-formed w.r.t. Object overrides
author mcimadamore
date Thu, 08 Nov 2012 17:17:10 +0000
parents d18de0997cba
children 5b858be3d094
files 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 test/tools/javac/lambda/TargetType48.java test/tools/javac/lambda/TargetType49.java test/tools/javac/lambda/TargetType49.out
diffstat 6 files changed, 130 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/code/Types.java	Wed Nov 07 11:39:20 2012 +0000
+++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Nov 08 17:17:10 2012 +0000
@@ -399,15 +399,10 @@
 
             @Override
             public boolean accepts(Symbol sym) {
-                    return sym.kind == Kinds.MTH &&
-                            (sym.flags() & (ABSTRACT | DEFAULT)) == ABSTRACT &&
-                            !overridesObjectMethod(origin, sym) &&
-                            notOverridden(sym);
-            }
-
-            private boolean notOverridden(Symbol msym) {
-                Symbol impl = ((MethodSymbol)msym).implementation(origin, Types.this, false);
-                return impl == null || (impl.flags() & (DEFAULT | ABSTRACT)) == ABSTRACT;
+                return sym.kind == Kinds.MTH &&
+                        (sym.flags() & (ABSTRACT | DEFAULT)) == ABSTRACT &&
+                        !overridesObjectMethod(origin, sym) &&
+                        (interfaceCandidates(origin.type, (MethodSymbol)sym).head.flags() & DEFAULT) == 0;
             }
         };
 
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Nov 07 11:39:20 2012 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Nov 08 17:17:10 2012 +0000
@@ -2191,10 +2191,16 @@
                 explicitParamTypes = TreeInfo.types(that.params);
             }
 
-            Type target = infer.instantiateFunctionalInterface(that, adjustTarget(pt()), explicitParamTypes, resultInfo.checkContext);
-            Type lambdaType = (target == Type.recoveryType) ?
-                    fallbackDescriptorType(that) :
-                    types.findDescriptorType(target);
+            Type target;
+            Type lambdaType;
+            if (pt() != Type.recoveryType) {
+                target = infer.instantiateFunctionalInterface(that, adjustTarget(pt()), explicitParamTypes, resultInfo.checkContext);
+                lambdaType = types.findDescriptorType(target);
+                chk.checkFunctionalInterface(that, target);
+            } else {
+                target = Type.recoveryType;
+                lambdaType = fallbackDescriptorType(that);
+            }
 
             if (!TreeInfo.isExplicitLambda(that)) {
                 //add param type info in the AST
@@ -2440,10 +2446,16 @@
                 typeargtypes = attribTypes(that.typeargs, localEnv);
             }
 
-            Type target = infer.instantiateFunctionalInterface(that, adjustTarget(pt()), null, resultInfo.checkContext);
-            Type desc = (target == Type.recoveryType) ?
-                    fallbackDescriptorType(that) :
-                    types.findDescriptorType(target);
+            Type target;
+            Type desc;
+            if (pt() != Type.recoveryType) {
+                target = infer.instantiateFunctionalInterface(that, adjustTarget(pt()), null, resultInfo.checkContext);
+                desc = types.findDescriptorType(target);
+                chk.checkFunctionalInterface(that, target);
+            } else {
+                target = Type.recoveryType;
+                desc = fallbackDescriptorType(that);
+            }
 
             List<Type> argtypes = desc.getParameterTypes();
 
--- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Wed Nov 07 11:39:20 2012 +0000
+++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Thu Nov 08 17:17:10 2012 +0000
@@ -2236,20 +2236,34 @@
         c.type = types.createErrorType(c, c.type);
         c.flags_field |= ACYCLIC;
     }
+    
+    /**
+     * Check that functional interface methods would make sense when seen
+     * from the perspective of the implementing class
+     */
+    void checkFunctionalInterface(JCTree tree, Type funcInterface) {
+        ClassType c = new ClassType(Type.noType, List.<Type>nil(), null);
+        ClassSymbol csym = new ClassSymbol(0, names.empty, c, syms.noSymbol);
+        c.interfaces_field = List.of(funcInterface);
+        c.supertype_field = syms.objectType;
+        c.tsym = csym;
+        csym.members_field = new Scope(csym);
+        csym.completer = null;
+        checkImplementations(tree, csym, csym);
+    }
 
     /** Check that all methods which implement some
      *  method conform to the method they implement.
      *  @param tree         The class definition whose members are checked.
      */
     void checkImplementations(JCClassDecl tree) {
-        checkImplementations(tree, tree.sym);
+        checkImplementations(tree, tree.sym, tree.sym);
     }
 //where
         /** Check that all methods which implement some
          *  method in `ic' conform to the method they implement.
          */
-        void checkImplementations(JCClassDecl tree, ClassSymbol ic) {
-            ClassSymbol origin = tree.sym;
+        void checkImplementations(JCTree tree, ClassSymbol origin, ClassSymbol ic) {
             for (List<Type> l = types.closure(ic.type); l.nonEmpty(); l = l.tail) {
                 ClassSymbol lc = (ClassSymbol)l.head.tsym;
                 if ((allowGenerics || origin != lc) && (lc.flags() & ABSTRACT) != 0) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType48.java	Thu Nov 08 17:17:10 2012 +0000
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012, 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 spurious functional interface conversion errors with default methods in target type
+ * @compile TargetType48.java
+ */
+
+class TargetType48 {
+    interface I1 {
+        void a();
+        void b();
+        void c();
+    }
+
+    interface I2 extends I1 {
+        default void a() { }
+    }
+
+    interface I3 extends I2 {
+        default void b() { }
+    }
+    
+    I3 i3 = ()->{ };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType49.java	Thu Nov 08 17:17:10 2012 +0000
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2012, 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 javac accepts ill-formed lambda/method reference targets
+ * @compile/fail/ref=TargetType49.out -XDrawDiagnostics TargetType49.java
+ */
+class TargetType49 {
+
+    interface F {
+        default Object clone() { return null; }
+        void m();
+    }
+    
+    F f1 = ()->{};
+    F f2 = this::g;
+    
+    void g() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType49.out	Thu Nov 08 17:17:10 2012 +0000
@@ -0,0 +1,3 @@
+TargetType49.java:36:12: compiler.err.override.weaker.access: (compiler.misc.cant.implement: clone(), java.lang.Object, clone(), TargetType49.F), public
+TargetType49.java:37:12: compiler.err.override.weaker.access: (compiler.misc.cant.implement: clone(), java.lang.Object, clone(), TargetType49.F), public
+2 errors