changeset 1475:ba59bf7fa23f

Bug Fixes: *) Missing accessibility check for target type when type-checking lambda/method reference *) Forgot to hg add test TargetType45
author mcimadamore
date Fri, 19 Oct 2012 17:48:08 +0100
parents 80cd7ed2bec4
children 1655737bb7ad
files 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/Resolve.java src/share/classes/com/sun/tools/javac/resources/compiler.properties test/tools/javac/diags/examples.not-yet.txt test/tools/javac/lambda/TargetType45.java test/tools/javac/lambda/TargetType45.out test/tools/javac/lambda/TargetType46.java test/tools/javac/lambda/TargetType46.out
diffstat 9 files changed, 173 insertions(+), 80 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Wed Oct 17 15:59:21 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Fri Oct 19 17:48:08 2012 +0100
@@ -2361,7 +2361,7 @@
             checkLambdaCompatible(that, lambdaType, resultInfo.checkContext, isSpeculativeRound);
             
             if (!isSpeculativeRound) {
-                checkAccessibleSAM(that, localEnv, resultInfo.checkContext.inferenceContext(), lambdaType);
+                checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), lambdaType, target);
             }
         } catch (Types.SAMConversionFailure ex) {
             JCDiagnostic cause = ex.getDiagnostic();
@@ -2396,16 +2396,22 @@
     }
     
     //where
-        private void checkAccessibleSAM(final DiagnosticPosition pos, final Env<AttrContext> env, final InferenceContext inferenceContext, final Type desc) {
-            if (inferenceContext.free(desc)) {
-                inferenceContext.addFreeTypeListener(List.of(desc), new FreeTypeListener() {
+        private void checkAccessibleTypes(final DiagnosticPosition pos, final Env<AttrContext> env, final InferenceContext inferenceContext, final Type... ts) {
+            checkAccessibleTypes(pos, env, inferenceContext, List.from(ts));
+        }
+    
+        private void checkAccessibleTypes(final DiagnosticPosition pos, final Env<AttrContext> env, final InferenceContext inferenceContext, final List<Type> ts) {
+            if (inferenceContext.free(ts)) {
+                inferenceContext.addFreeTypeListener(ts, new FreeTypeListener() {
                     @Override
                     public void typesInferred(InferenceContext inferenceContext) {
-                        checkAccessibleSAM(pos, env, inferenceContext, inferenceContext.asInstType(desc, types));
+                        checkAccessibleTypes(pos, env, inferenceContext, inferenceContext.asInstTypes(ts, types));
                     }
                 });
             } else {
-                chk.checkAccessibleSAM(pos, env, desc);
+                for (Type t : ts) {
+                    rs.checkAccessibleType(env, t);
+                }
             } 
         }
         
@@ -2840,7 +2846,7 @@
                     resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE;
             checkReferenceCompatible(that, desc, refType, resultInfo.checkContext, isSpeculativeRound);
             if (!isSpeculativeRound) {
-                checkAccessibleSAM(that, localEnv, resultInfo.checkContext.inferenceContext(), desc);
+                checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), desc, target);
             }
             result = check(that, target, VAL, resultInfo);
         } catch (Types.SAMConversionFailure ex) {
--- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Wed Oct 17 15:59:21 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Fri Oct 19 17:48:08 2012 +0100
@@ -963,67 +963,7 @@
                 && types.isSubtypeUnchecked(actual, types.interfaces(formal), warn))
                 return;
         }
-
-        void checkAccessibleSAM(DiagnosticPosition pos, Env<AttrContext> env, Type desc) {
-            SamAccessibilityChecker samAccessibilityChecker =
-                    new SamAccessibilityChecker(env);
-            //check args accessibility (only if implicit parameter types)
-            for (Type arg : desc.getParameterTypes()) {
-                if (!samAccessibilityChecker.visit(arg)) {
-                    log.error(pos, "cant.access.argtype.in.sam.desc", arg);
-                    return;
-                }
-            }
-            //check return type accessibility
-            if (!samAccessibilityChecker.visit(desc.getReturnType())) {
-                log.error(pos, "cant.access.return.in.sam.desc", desc.getReturnType());
-                return;
-            }
-            //check thrown types accessibility
-            for (Type thrown : desc.getThrownTypes()) {
-                if (!samAccessibilityChecker.visit(thrown)) {
-                    log.error(pos, "cant.access.thrown.in.sam.desc", thrown);
-                    return;
-                }
-            }
-        }
-            
-        class SamAccessibilityChecker extends Types.UnaryVisitor<Boolean> {
-            
-            Env<AttrContext> env;
-
-            SamAccessibilityChecker(Env<AttrContext> env) {
-                this.env = env;
-            }
-
-            Boolean visit(List<Type> ts) {
-                for (Type t : ts) {
-                    if (!visit(t))
-                        return false;
-                }
-                return true;
-            }
-
-            public Boolean visitType(Type t, Void s) {
-                return true;
-            }
-
-            @Override
-            public Boolean visitArrayType(ArrayType t, Void s) {
-                return visit(t.elemtype);
-            }
-
-            @Override
-            public Boolean visitClassType(ClassType t, Void s) {
-                return rs.isAccessible(env, t, true) &&
-                        visit(t.getTypeArguments());
-            }
-
-            @Override
-            public Boolean visitWildcardType(WildcardType t, Void s) {
-                return visit(t.type);
-            }
-        };
+        
     /**
      * Check that type 't' is a valid instantiation of a generic class
      * (see JLS 4.5)
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Wed Oct 17 15:59:21 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Oct 19 17:48:08 2012 +0100
@@ -436,6 +436,60 @@
                 c = c.owner.enclClass();
             return c != null;
         }
+        
+    /** 
+     * Performs a recursive scan of a type looking for accessibility problems
+     * from current attribution environment
+     */
+    void checkAccessibleType(Env<AttrContext> env, Type t) {
+        accessibilityChecker.visit(t, env);
+    }
+
+    /** 
+     * Accessibility type-visitor
+     */
+    Types.SimpleVisitor<Void, Env<AttrContext>> accessibilityChecker =
+            new Types.SimpleVisitor<Void, Env<AttrContext>>() {
+
+        void visit(List<Type> ts, Env<AttrContext> env) {
+            for (Type t : ts) {
+                visit(t, env);
+            }
+        }
+
+        public Void visitType(Type t, Env<AttrContext> env) {
+            return null;
+        }
+
+        @Override
+        public Void visitArrayType(ArrayType t, Env<AttrContext> env) {
+            visit(t.elemtype, env);
+            return null;
+        }
+
+        @Override
+        public Void visitClassType(ClassType t, Env<AttrContext> env) {
+            visit(t.getTypeArguments(), env);
+            if (!isAccessible(env, t, true)) {
+                accessBase(new AccessError(t.tsym), env.tree.pos(), env.enclClass.sym, t, t.tsym.name, true);
+            }
+            return null;
+        }
+
+        @Override
+        public Void visitWildcardType(WildcardType t, Env<AttrContext> env) {
+            visit(t.type, env);
+            return null;
+        }
+
+        @Override
+        public Void visitMethodType(MethodType t, Env<AttrContext> env) {
+            visit(t.getParameterTypes(), env);
+            visit(t.getReturnType(), env);
+            visit(t.getThrownTypes(), env);
+            return null;
+        }
+    };
 
     /** Try to instantiate the type of a method so that it fits
      *  given type arguments and argument types. If succesful, return
--- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Wed Oct 17 15:59:21 2012 +0100
+++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri Oct 19 17:48:08 2012 +0100
@@ -179,15 +179,6 @@
 compiler.misc.cyclic.lambda.inference=\
     cyclic inference - cannot infer target type for given lambda/method reference expression
 
-compiler.err.cant.access.argtype.in.sam.desc=\
-    cannot access parameter type {0} in target SAM descriptor
-
-compiler.err.cant.access.return.in.sam.desc=\
-    cannot access return type {0} in target SAM descriptor
-
-compiler.err.cant.access.thrown.in.sam.desc=\
-    cannot access thrown type {0} in target SAM descriptor
-
 compiler.misc.no.target.method.for.lambda.conv=\
     no target method for lambda conversion found in {0} {1}
 
--- a/test/tools/javac/diags/examples.not-yet.txt	Wed Oct 17 15:59:21 2012 +0100
+++ b/test/tools/javac/diags/examples.not-yet.txt	Fri Oct 19 17:48:08 2012 +0100
@@ -104,9 +104,6 @@
 compiler.warn.unknown.enum.constant                     # in bad class file
 compiler.warn.unknown.enum.constant.reason              # in bad class file
 compiler.err.break.inside.lambda                                                 #LAMBDA
-compiler.err.cant.access.argtype.in.sam.desc                                     #LAMBDA
-compiler.err.cant.access.return.in.sam.desc                                      #LAMBDA
-compiler.err.cant.access.thrown.in.sam.desc                                      #LAMBDA
 compiler.err.cant.ref.non.effectively.final.var                                  #LAMBDA
 compiler.err.cont.inside.lambda                                                  #LAMBDA
 compiler.err.default.overrides.object.member                                     #LAMBDA
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType45.java	Fri Oct 19 17:48:08 2012 +0100
@@ -0,0 +1,50 @@
+/*
+ * 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 compiler crashes during flow analysis as it fails to report diagnostics during attribution
+ * @compile/fail/ref=TargetType45.out -XDrawDiagnostics TargetType45.java
+ */
+class TargetType45 {
+    
+    interface Predicate<X> {
+        boolean apply(X x);
+    }
+
+    interface Mapper<X, Y> {
+        Y apply(X x);
+    }
+
+    class Foo<X> {
+        Foo<X> filter(Predicate<? super X> p) { return null; }
+    }
+
+    static <U, V> Predicate<U> compose(Predicate<? super V> pi, Mapper<? super U, ? extends V> m) { return null; }
+
+    static Predicate<Integer> isOdd = i -> i % 2 != 0;
+
+    void top10Counties(Foo<String> foos) {
+        foos.filter(compose(isOdd, (String e) -> e.length()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType45.out	Fri Oct 19 17:48:08 2012 +0100
@@ -0,0 +1,2 @@
+TargetType45.java:48:28: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: U,V, (compiler.misc.inconvertible.types: TargetType45.Mapper<java.lang.String,java.lang.Integer>, TargetType45.Mapper<? super java.lang.Object,? extends java.lang.Integer>))
+1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType46.java	Fri Oct 19 17:48:08 2012 +0100
@@ -0,0 +1,50 @@
+/*
+ * 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 compiler doesn't report accessibility problem due to inaccessible target
+ * @compile/fail/ref=TargetType46.out -XDrawDiagnostics TargetType46.java
+ */
+import java.util.*;
+
+class TargetType46Outer {
+    
+    private interface PI {
+       void m();
+    }
+
+    void m(PI p) { }
+    void m(List<PI> p) { }
+}
+
+class TargetType46 {
+    void test(TargetType46Outer outer) {
+        outer.m(()->{}); //access error
+        outer.m(this::g); //access error
+        outer.m(new ArrayList<>()); //ok
+        outer.m(Collections.emptyList()); //ok
+    }
+
+    void g() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/lambda/TargetType46.out	Fri Oct 19 17:48:08 2012 +0100
@@ -0,0 +1,3 @@
+TargetType46.java:43:17: compiler.err.report.access: TargetType46Outer.PI, private, TargetType46Outer
+TargetType46.java:44:17: compiler.err.report.access: TargetType46Outer.PI, private, TargetType46Outer
+2 errors