Thu, 25 Jul 2013 14:51:40 +0100
8020843: javac crashes on accessibility check with method reference with typevar receiver
Summary: method reference overload check doesn't walk through type-variable receivers
Reviewed-by: jjg
aoqi@0 | 1 | /* |
aoqi@0 | 2 | * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. |
aoqi@0 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
aoqi@0 | 4 | * |
aoqi@0 | 5 | * This code is free software; you can redistribute it and/or modify it |
aoqi@0 | 6 | * under the terms of the GNU General Public License version 2 only, as |
aoqi@0 | 7 | * published by the Free Software Foundation. Oracle designates this |
aoqi@0 | 8 | * particular file as subject to the "Classpath" exception as provided |
aoqi@0 | 9 | * by Oracle in the LICENSE file that accompanied this code. |
aoqi@0 | 10 | * |
aoqi@0 | 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
aoqi@0 | 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
aoqi@0 | 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
aoqi@0 | 14 | * version 2 for more details (a copy is included in the LICENSE file that |
aoqi@0 | 15 | * accompanied this code). |
aoqi@0 | 16 | * |
aoqi@0 | 17 | * You should have received a copy of the GNU General Public License version |
aoqi@0 | 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
aoqi@0 | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
aoqi@0 | 20 | * |
aoqi@0 | 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
aoqi@0 | 22 | * or visit www.oracle.com if you need additional information or have any |
aoqi@0 | 23 | * questions. |
aoqi@0 | 24 | */ |
aoqi@0 | 25 | |
aoqi@0 | 26 | /** |
aoqi@0 | 27 | * @test |
aoqi@0 | 28 | * @bug 8003639 |
aoqi@0 | 29 | * @summary convert lambda testng tests to jtreg and add them |
aoqi@0 | 30 | * @run testng LambdaTranslationTest2 |
aoqi@0 | 31 | */ |
aoqi@0 | 32 | |
aoqi@0 | 33 | import org.testng.annotations.Test; |
aoqi@0 | 34 | |
aoqi@0 | 35 | import java.util.ArrayList; |
aoqi@0 | 36 | import java.util.List; |
aoqi@0 | 37 | |
aoqi@0 | 38 | import static org.testng.Assert.assertEquals; |
aoqi@0 | 39 | import static org.testng.Assert.assertTrue; |
aoqi@0 | 40 | |
aoqi@0 | 41 | /** |
aoqi@0 | 42 | * LambdaTranslationTest2 -- end-to-end smoke tests for lambda evaluation |
aoqi@0 | 43 | */ |
aoqi@0 | 44 | |
aoqi@0 | 45 | @Test |
aoqi@0 | 46 | public class LambdaTranslationTest2 { |
aoqi@0 | 47 | |
aoqi@0 | 48 | final String dummy = "dummy"; |
aoqi@0 | 49 | |
aoqi@0 | 50 | public void testLambdas() { |
aoqi@0 | 51 | TPredicate<String> isEmpty = s -> s.isEmpty(); |
aoqi@0 | 52 | assertTrue(isEmpty.test("")); |
aoqi@0 | 53 | assertTrue(!isEmpty.test("foo")); |
aoqi@0 | 54 | |
aoqi@0 | 55 | TPredicate<Object> oIsEmpty = s -> ((String) s).isEmpty(); |
aoqi@0 | 56 | assertTrue(oIsEmpty.test("")); |
aoqi@0 | 57 | assertTrue(!oIsEmpty.test("foo")); |
aoqi@0 | 58 | |
aoqi@0 | 59 | TPredicate<Object> alwaysTrue = o -> true; |
aoqi@0 | 60 | assertTrue(alwaysTrue.test("")); |
aoqi@0 | 61 | assertTrue(alwaysTrue.test(null)); |
aoqi@0 | 62 | |
aoqi@0 | 63 | TPredicate<Object> alwaysFalse = o -> false; |
aoqi@0 | 64 | assertTrue(!alwaysFalse.test("")); |
aoqi@0 | 65 | assertTrue(!alwaysFalse.test(null)); |
aoqi@0 | 66 | |
aoqi@0 | 67 | // tests local capture |
aoqi@0 | 68 | String foo = "foo"; |
aoqi@0 | 69 | TPredicate<String> equalsFoo = s -> s.equals(foo); |
aoqi@0 | 70 | assertTrue(!equalsFoo.test("")); |
aoqi@0 | 71 | assertTrue(equalsFoo.test("foo")); |
aoqi@0 | 72 | |
aoqi@0 | 73 | // tests instance capture |
aoqi@0 | 74 | TPredicate<String> equalsDummy = s -> s.equals(dummy); |
aoqi@0 | 75 | assertTrue(!equalsDummy.test("")); |
aoqi@0 | 76 | assertTrue(equalsDummy.test("dummy")); |
aoqi@0 | 77 | |
aoqi@0 | 78 | TMapper<Object, Object> ident = s -> s; |
aoqi@0 | 79 | |
aoqi@0 | 80 | assertEquals("blarf", ident.map("blarf")); |
aoqi@0 | 81 | assertEquals("wooga", ident.map("wooga")); |
aoqi@0 | 82 | assertTrue("wooga" == ident.map("wooga")); |
aoqi@0 | 83 | |
aoqi@0 | 84 | // constant capture |
aoqi@0 | 85 | TMapper<Object, Object> prefixer = s -> "p" + s; |
aoqi@0 | 86 | assertEquals("pblarf", prefixer.map("blarf")); |
aoqi@0 | 87 | assertEquals("pwooga", prefixer.map("wooga")); |
aoqi@0 | 88 | |
aoqi@0 | 89 | // instance capture |
aoqi@0 | 90 | TMapper<Object, Object> prefixer2 = s -> dummy + s; |
aoqi@0 | 91 | assertEquals("dummyblarf", prefixer2.map("blarf")); |
aoqi@0 | 92 | assertEquals("dummywooga", prefixer2.map("wooga")); |
aoqi@0 | 93 | } |
aoqi@0 | 94 | |
aoqi@0 | 95 | interface Factory<T> { |
aoqi@0 | 96 | T make(); |
aoqi@0 | 97 | } |
aoqi@0 | 98 | |
aoqi@0 | 99 | interface StringFactory extends Factory<String> { } |
aoqi@0 | 100 | |
aoqi@0 | 101 | interface StringFactory2 extends Factory<String> { |
aoqi@0 | 102 | String make(); |
aoqi@0 | 103 | } |
aoqi@0 | 104 | |
aoqi@0 | 105 | public void testBridges() { |
aoqi@0 | 106 | Factory<String> of = () -> "y"; |
aoqi@0 | 107 | Factory<?> ef = () -> "z"; |
aoqi@0 | 108 | |
aoqi@0 | 109 | assertEquals("y", of.make()); |
aoqi@0 | 110 | assertEquals("y", ((Factory<?>) of).make()); |
aoqi@0 | 111 | assertEquals("y", ((Factory) of).make()); |
aoqi@0 | 112 | |
aoqi@0 | 113 | assertEquals("z", ef.make()); |
aoqi@0 | 114 | assertEquals("z", ((Factory) ef).make()); |
aoqi@0 | 115 | } |
aoqi@0 | 116 | |
aoqi@0 | 117 | public void testBridgesImplicitSpecialization() { |
aoqi@0 | 118 | StringFactory sf = () -> "x"; |
aoqi@0 | 119 | |
aoqi@0 | 120 | assertEquals("x", sf.make()); |
aoqi@0 | 121 | assertEquals("x", ((Factory<String>) sf).make()); |
aoqi@0 | 122 | assertEquals("x", ((Factory<?>) sf).make()); |
aoqi@0 | 123 | assertEquals("x", ((Factory) sf).make()); |
aoqi@0 | 124 | } |
aoqi@0 | 125 | |
aoqi@0 | 126 | public void testBridgesExplicitSpecialization() { |
aoqi@0 | 127 | StringFactory2 sf = () -> "x"; |
aoqi@0 | 128 | |
aoqi@0 | 129 | assertEquals("x", sf.make()); |
aoqi@0 | 130 | assertEquals("x", ((Factory<String>) sf).make()); |
aoqi@0 | 131 | assertEquals("x", ((Factory<?>) sf).make()); |
aoqi@0 | 132 | assertEquals("x", ((Factory) sf).make()); |
aoqi@0 | 133 | } |
aoqi@0 | 134 | |
aoqi@0 | 135 | public void testSuperCapture() { |
aoqi@0 | 136 | class A { |
aoqi@0 | 137 | String make() { return "x"; } |
aoqi@0 | 138 | } |
aoqi@0 | 139 | |
aoqi@0 | 140 | class B extends A { |
aoqi@0 | 141 | void testSuperCapture() { |
aoqi@0 | 142 | StringFactory sf = () -> super.make(); |
aoqi@0 | 143 | assertEquals("x", sf.make()); |
aoqi@0 | 144 | } |
aoqi@0 | 145 | } |
aoqi@0 | 146 | |
aoqi@0 | 147 | new B().testSuperCapture(); |
aoqi@0 | 148 | } |
aoqi@0 | 149 | |
aoqi@0 | 150 | interface WidenD { |
aoqi@0 | 151 | public String m(float a0, double a1); |
aoqi@0 | 152 | } |
aoqi@0 | 153 | |
aoqi@0 | 154 | interface WidenS { |
aoqi@0 | 155 | public String m(byte a0, short a1); |
aoqi@0 | 156 | } |
aoqi@0 | 157 | |
aoqi@0 | 158 | interface WidenI { |
aoqi@0 | 159 | public String m(byte a0, short a1, char a2, int a3); |
aoqi@0 | 160 | } |
aoqi@0 | 161 | |
aoqi@0 | 162 | interface WidenL { |
aoqi@0 | 163 | public String m(byte a0, short a1, char a2, int a3, long a4); |
aoqi@0 | 164 | } |
aoqi@0 | 165 | |
aoqi@0 | 166 | interface Box { |
aoqi@0 | 167 | public String m(byte a0, short a1, char a2, int a3, long a4, boolean a5, float a6, double a7); |
aoqi@0 | 168 | } |
aoqi@0 | 169 | |
aoqi@0 | 170 | static String pb(Byte a0, Short a1, Character a2, Integer a3, Long a4, Boolean a5, Float a6, Double a7) { |
aoqi@0 | 171 | return String.format("b%d s%d c%c i%d j%d z%b f%f d%f", a0, a1, a2, a3, a4, a5, a6, a7); |
aoqi@0 | 172 | } |
aoqi@0 | 173 | |
aoqi@0 | 174 | static String pwI1(int a0, int a1, int a2, int a3) { |
aoqi@0 | 175 | return String.format("b%d s%d c%d i%d", a0, a1, a2, a3); |
aoqi@0 | 176 | } |
aoqi@0 | 177 | |
aoqi@0 | 178 | static String pwI2(Integer a0, Integer a1, Integer a2, Integer a3) { |
aoqi@0 | 179 | return String.format("b%d s%d c%d i%d", a0, a1, a2, a3); |
aoqi@0 | 180 | } |
aoqi@0 | 181 | |
aoqi@0 | 182 | static String pwL1(long a0, long a1, long a2, long a3, long a4) { |
aoqi@0 | 183 | return String.format("b%d s%d c%d i%d j%d", a0, a1, a2, a3, a4); |
aoqi@0 | 184 | } |
aoqi@0 | 185 | |
aoqi@0 | 186 | static String pwL2(Long a0, Long a1, Long a2, Long a3, Long a4) { |
aoqi@0 | 187 | return String.format("b%d s%d c%d i%d j%d", a0, a1, a2, a3, a4); |
aoqi@0 | 188 | } |
aoqi@0 | 189 | |
aoqi@0 | 190 | static String pwS1(short a0, short a1) { |
aoqi@0 | 191 | return String.format("b%d s%d", a0, a1); |
aoqi@0 | 192 | } |
aoqi@0 | 193 | |
aoqi@0 | 194 | static String pwS2(Short a0, Short a1) { |
aoqi@0 | 195 | return String.format("b%d s%d", a0, a1); |
aoqi@0 | 196 | } |
aoqi@0 | 197 | |
aoqi@0 | 198 | static String pwD1(double a0, double a1) { |
aoqi@0 | 199 | return String.format("f%f d%f", a0, a1); |
aoqi@0 | 200 | } |
aoqi@0 | 201 | |
aoqi@0 | 202 | static String pwD2(Double a0, Double a1) { |
aoqi@0 | 203 | return String.format("f%f d%f", a0, a1); |
aoqi@0 | 204 | } |
aoqi@0 | 205 | |
aoqi@0 | 206 | public void testPrimitiveWidening() { |
aoqi@0 | 207 | WidenS ws1 = LambdaTranslationTest2::pwS1; |
aoqi@0 | 208 | assertEquals("b1 s2", ws1.m((byte) 1, (short) 2)); |
aoqi@0 | 209 | |
aoqi@0 | 210 | WidenD wd1 = LambdaTranslationTest2::pwD1; |
aoqi@0 | 211 | assertEquals("f1.000000 d2.000000", wd1.m(1.0f, 2.0)); |
aoqi@0 | 212 | |
aoqi@0 | 213 | WidenI wi1 = LambdaTranslationTest2::pwI1; |
aoqi@0 | 214 | assertEquals("b1 s2 c3 i4", wi1.m((byte) 1, (short) 2, (char) 3, 4)); |
aoqi@0 | 215 | |
aoqi@0 | 216 | WidenL wl1 = LambdaTranslationTest2::pwL1; |
aoqi@0 | 217 | assertEquals("b1 s2 c3 i4 j5", wl1.m((byte) 1, (short) 2, (char) 3, 4, 5L)); |
aoqi@0 | 218 | |
aoqi@0 | 219 | // @@@ TODO: clarify spec on widen+box conversion |
aoqi@0 | 220 | } |
aoqi@0 | 221 | |
aoqi@0 | 222 | interface Unbox { |
aoqi@0 | 223 | public String m(Byte a0, Short a1, Character a2, Integer a3, Long a4, Boolean a5, Float a6, Double a7); |
aoqi@0 | 224 | } |
aoqi@0 | 225 | |
aoqi@0 | 226 | static String pu(byte a0, short a1, char a2, int a3, long a4, boolean a5, float a6, double a7) { |
aoqi@0 | 227 | return String.format("b%d s%d c%c i%d j%d z%b f%f d%f", a0, a1, a2, a3, a4, a5, a6, a7); |
aoqi@0 | 228 | } |
aoqi@0 | 229 | |
aoqi@0 | 230 | public void testUnboxing() { |
aoqi@0 | 231 | Unbox u = LambdaTranslationTest2::pu; |
aoqi@0 | 232 | assertEquals("b1 s2 cA i4 j5 ztrue f6.000000 d7.000000", u.m((byte)1, (short) 2, 'A', 4, 5L, true, 6.0f, 7.0)); |
aoqi@0 | 233 | } |
aoqi@0 | 234 | |
aoqi@0 | 235 | public void testBoxing() { |
aoqi@0 | 236 | Box b = LambdaTranslationTest2::pb; |
aoqi@0 | 237 | assertEquals("b1 s2 cA i4 j5 ztrue f6.000000 d7.000000", b.m((byte) 1, (short) 2, 'A', 4, 5L, true, 6.0f, 7.0)); |
aoqi@0 | 238 | } |
aoqi@0 | 239 | |
aoqi@0 | 240 | static boolean cc(Object o) { |
aoqi@0 | 241 | return ((String) o).equals("foo"); |
aoqi@0 | 242 | } |
aoqi@0 | 243 | |
aoqi@0 | 244 | public void testArgCastingAdaptation() { |
aoqi@0 | 245 | TPredicate<String> p = LambdaTranslationTest2::cc; |
aoqi@0 | 246 | assertTrue(p.test("foo")); |
aoqi@0 | 247 | assertTrue(!p.test("bar")); |
aoqi@0 | 248 | } |
aoqi@0 | 249 | |
aoqi@0 | 250 | interface SonOfPredicate<T> extends TPredicate<T> { } |
aoqi@0 | 251 | |
aoqi@0 | 252 | public void testExtendsSAM() { |
aoqi@0 | 253 | SonOfPredicate<String> p = s -> s.isEmpty(); |
aoqi@0 | 254 | assertTrue(p.test("")); |
aoqi@0 | 255 | assertTrue(!p.test("foo")); |
aoqi@0 | 256 | } |
aoqi@0 | 257 | |
aoqi@0 | 258 | public void testConstructorRef() { |
aoqi@0 | 259 | Factory<List<String>> lf = ArrayList<String>::new; |
aoqi@0 | 260 | List<String> list = lf.make(); |
aoqi@0 | 261 | assertTrue(list instanceof ArrayList); |
aoqi@0 | 262 | assertTrue(list != lf.make()); |
aoqi@0 | 263 | list.add("a"); |
aoqi@0 | 264 | assertEquals("[a]", list.toString()); |
aoqi@0 | 265 | } |
aoqi@0 | 266 | |
aoqi@0 | 267 | private static String privateMethod() { |
aoqi@0 | 268 | return "private"; |
aoqi@0 | 269 | } |
aoqi@0 | 270 | |
aoqi@0 | 271 | public void testPrivateMethodRef() { |
aoqi@0 | 272 | Factory<String> sf = LambdaTranslationTest2::privateMethod; |
aoqi@0 | 273 | assertEquals("private", sf.make()); |
aoqi@0 | 274 | } |
aoqi@0 | 275 | |
aoqi@0 | 276 | private interface PrivateIntf { |
aoqi@0 | 277 | String make(); |
aoqi@0 | 278 | } |
aoqi@0 | 279 | |
aoqi@0 | 280 | public void testPrivateIntf() { |
aoqi@0 | 281 | PrivateIntf p = () -> "foo"; |
aoqi@0 | 282 | assertEquals("foo", p.make()); |
aoqi@0 | 283 | } |
aoqi@0 | 284 | |
aoqi@0 | 285 | interface Op<T> { |
aoqi@0 | 286 | public T op(T a, T b); |
aoqi@0 | 287 | } |
aoqi@0 | 288 | |
aoqi@0 | 289 | public void testBoxToObject() { |
aoqi@0 | 290 | Op<Integer> maxer = Math::max; |
aoqi@0 | 291 | for (int i=-100000; i < 100000; i += 100) |
aoqi@0 | 292 | for (int j=-100000; j < 100000; j += 99) { |
aoqi@0 | 293 | assertEquals((int) maxer.op(i,j), Math.max(i,j)); |
aoqi@0 | 294 | } |
aoqi@0 | 295 | } |
aoqi@0 | 296 | |
aoqi@0 | 297 | protected static String protectedMethod() { |
aoqi@0 | 298 | return "protected"; |
aoqi@0 | 299 | } |
aoqi@0 | 300 | |
aoqi@0 | 301 | public void testProtectedMethodRef() { |
aoqi@0 | 302 | Factory<String> sf = LambdaTranslationTest2::protectedMethod; |
aoqi@0 | 303 | assertEquals("protected", sf.make()); |
aoqi@0 | 304 | } |
aoqi@0 | 305 | |
aoqi@0 | 306 | class Inner1 { |
aoqi@0 | 307 | String m1() { |
aoqi@0 | 308 | return "Inner1.m1()"; |
aoqi@0 | 309 | } |
aoqi@0 | 310 | |
aoqi@0 | 311 | class Inner2 { |
aoqi@0 | 312 | public String m1() { |
aoqi@0 | 313 | return "Inner1.Inner2.m1()"; |
aoqi@0 | 314 | } |
aoqi@0 | 315 | |
aoqi@0 | 316 | protected String m2() { |
aoqi@0 | 317 | return "Inner1.Inner2.m2()"; |
aoqi@0 | 318 | } |
aoqi@0 | 319 | |
aoqi@0 | 320 | String m3() { |
aoqi@0 | 321 | return "Inner1.Inner2.m3()"; |
aoqi@0 | 322 | } |
aoqi@0 | 323 | |
aoqi@0 | 324 | class Inner3<T> { |
aoqi@0 | 325 | T t = null; |
aoqi@0 | 326 | Inner3(T t) { |
aoqi@0 | 327 | this.t = t; |
aoqi@0 | 328 | } |
aoqi@0 | 329 | T m1() { |
aoqi@0 | 330 | return t; |
aoqi@0 | 331 | } |
aoqi@0 | 332 | } |
aoqi@0 | 333 | } |
aoqi@0 | 334 | } |
aoqi@0 | 335 | |
aoqi@0 | 336 | public void testInnerClassMethodRef() { |
aoqi@0 | 337 | Factory<String> fs = new Inner1()::m1; |
aoqi@0 | 338 | assertEquals("Inner1.m1()", fs.make()); |
aoqi@0 | 339 | |
aoqi@0 | 340 | fs = new Inner1().new Inner2()::m1; |
aoqi@0 | 341 | assertEquals("Inner1.Inner2.m1()", fs.make()); |
aoqi@0 | 342 | |
aoqi@0 | 343 | fs = new Inner1().new Inner2()::m2; |
aoqi@0 | 344 | assertEquals("Inner1.Inner2.m2()", fs.make()); |
aoqi@0 | 345 | |
aoqi@0 | 346 | fs = new Inner1().new Inner2()::m3; |
aoqi@0 | 347 | assertEquals("Inner1.Inner2.m3()", fs.make()); |
aoqi@0 | 348 | |
aoqi@0 | 349 | fs = new Inner1().new Inner2().new Inner3<String>("Inner1.Inner2.Inner3")::m1; |
aoqi@0 | 350 | assertEquals("Inner1.Inner2.Inner3", fs.make()); |
aoqi@0 | 351 | |
aoqi@0 | 352 | Factory<Integer> fsi = new Inner1().new Inner2().new Inner3<Integer>(100)::m1; |
aoqi@0 | 353 | assertEquals(100, (int)fsi.make()); |
aoqi@0 | 354 | } |
aoqi@0 | 355 | } |