| // Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| package lambdadesugaringnplus; | |
| import java.io.Serializable; | |
| import java.lang.annotation.Annotation; | |
| import java.lang.annotation.Retention; | |
| import java.lang.annotation.RetentionPolicy; | |
| import lambdadesugaringnplus.other.ClassWithDefaultPackagePrivate; | |
| import lambdadesugaringnplus.other.InterfaceWithDefaultPackagePrivate; | |
| public class LambdasWithStaticAndDefaultMethods { | |
| interface I { | |
| String iRegular(); | |
| static String iStatic() { | |
| return "I::iStatic()"; | |
| } | |
| default String iDefault() { | |
| return "I::iDefault()"; | |
| } | |
| default String iDefaultOverridden() { | |
| return "I::iDefaultOverridden()"; | |
| } | |
| default II stateless() { | |
| return () -> "I::stateless()"; | |
| } | |
| default II stateful() { | |
| return () -> "I::captureThis(" + stateless().iRegular() + ")"; | |
| } | |
| } | |
| static class C implements I { | |
| @Override | |
| public String iRegular() { | |
| return "C::iRegular()"; | |
| } | |
| @Override | |
| public String iDefaultOverridden() { | |
| return "C::iDefaultOverridden()"; | |
| } | |
| } | |
| interface II extends I { | |
| static String iStatic() { | |
| II ii = I::iStatic; | |
| return "II::iStatic(" + ((I) I::iStatic).iRegular() + | |
| "|" + ((II) ii::iDefaultOverridden).iRegular() + | |
| "|" + ((II) String::new).iRegular() + | |
| "|" + ((II) ii::iRegular).iRegular() + ")"; | |
| } | |
| default String iDefaultOverridden() { | |
| return "II::iDefault(" + ((I) this::iDefault).iRegular() + | |
| "|" + ((II) "One-Two-Three"::intern).iRegular() + | |
| "|" + ((II) this::iDefault).iRegular() + ")"; | |
| } | |
| } | |
| interface P { | |
| String get(); | |
| } | |
| static void p(P p) { | |
| System.out.println(p.get()); | |
| } | |
| interface X<T> { | |
| String foo(T t); | |
| } | |
| interface Y<T extends I> extends X<T> { | |
| String foo(T t); | |
| } | |
| interface Z extends Y<II> { | |
| String foo(II t); | |
| } | |
| interface G<T> { | |
| T foo(T t); | |
| } | |
| interface B38257361_I1<T extends Number> { | |
| default T copy(T t) { | |
| return t; | |
| } | |
| } | |
| interface B38257361_I2 extends B38257361_I1<Integer> { | |
| @Override | |
| default Integer copy(Integer t) { | |
| return B38257361_I1.super.copy(t); | |
| } | |
| } | |
| static class B38257361_C implements B38257361_I2 { | |
| } | |
| static class B38257361 { | |
| private B38257361_C c = new B38257361_C(); | |
| public Integer test(Integer i) { | |
| return c.copy(i); | |
| } | |
| @SuppressWarnings({"rawtypes", "unchecked"}) | |
| public Number test(Number n) { | |
| return ((B38257361_I1) c).copy(n); | |
| } | |
| public static void test() { | |
| B38257361 l = new B38257361(); | |
| Integer i = new Integer(1); | |
| if (i.equals(l.test(i))) { | |
| System.out.println("Check 1: OK"); | |
| } else { | |
| System.out.println("Check 1: NOT OK"); | |
| } | |
| if (i.equals(l.test((Number) i))) { | |
| System.out.println("Check 2: OK"); | |
| } else { | |
| System.out.println("Check 2: NOT OK"); | |
| } | |
| try { | |
| Double d = new Double(1); | |
| if (d.equals(l.test((Number) d))) { | |
| System.out.println("Check 3: NOT OK, classCastException expected"); | |
| } else { | |
| System.out.println("Check 3: NOT OK, classCastException expected"); | |
| } | |
| System.out.println("Error, ClassCastException is expected"); | |
| } catch (ClassCastException e) { | |
| // Class cast into the bridge method is expected | |
| System.out.println("OK, ClassCastException is expected"); | |
| } | |
| } | |
| } | |
| static class B78901754 { | |
| public static class A { | |
| public final String msg; | |
| public A(String msg) { | |
| this.msg = msg; | |
| } | |
| } | |
| public static class B extends A { | |
| public B(String msg) { | |
| super(msg); | |
| } | |
| } | |
| public interface IAA { | |
| A[] foo(A[] p); | |
| } | |
| public interface IAB { | |
| A[] foo(B[] p); | |
| } | |
| public interface IBA { | |
| B[] foo(A[] p); | |
| } | |
| public interface IBB { | |
| B[] foo(B[] p); | |
| } | |
| public static A[] fooAA(A[] p) { | |
| return new A[]{new A("fooAA")}; | |
| } | |
| public static A[] fooBA(B[] p) { | |
| return new A[]{new A("fooBA")}; | |
| } | |
| public static B[] fooAB(A[] p) { | |
| return new B[]{new B("fooAB")}; | |
| } | |
| public static B[] fooBB(B[] p) { | |
| return new B[]{new B("fooBB")}; | |
| } | |
| public static void testAA(IAA i) { | |
| System.out.println(i.foo(null)[0].msg); | |
| } | |
| public static void testAB(IAB i) { | |
| System.out.println(i.foo(null)[0].msg); | |
| } | |
| public static void testBA(IBA i) { | |
| System.out.println(i.foo(null)[0].msg); | |
| } | |
| public static void testBB(IBB i) { | |
| System.out.println(i.foo(null)[0].msg); | |
| } | |
| public static void test() { | |
| testAA(B78901754::fooAA); | |
| testAA(B78901754::fooAB); | |
| // testAA(B78901754::fooBA); javac error: incompatible types: A[] cannot be converted to B[] | |
| // testAA(B78901754::fooBB); javac error: incompatible types: A[] cannot be converted to B[] | |
| testAB(B78901754::fooAA); | |
| testAB(B78901754::fooAB); | |
| testAB(B78901754::fooBA); | |
| testAB(B78901754::fooBB); | |
| // testBA(B78901754::fooAA); javac error: A[] cannot be converted to B[] | |
| testBA(B78901754::fooAB); | |
| // testBA(B78901754::fooBA); javac error: incompatible types: A[] cannot be converted to B[] | |
| // testBA(B78901754::fooBB); javac error: incompatible types: A[] cannot be converted to B[] | |
| // testBB(B78901754::fooAA); javac error: A[] cannot be converted to B[] | |
| testBB(B78901754::fooAB); | |
| // testBB(B78901754::fooBA); javac error: A[] cannot be converted to B[] | |
| testBB(B78901754::fooBB); | |
| } | |
| } | |
| interface B38257037_I1 { | |
| default Number getNumber() { | |
| return new Integer(1); | |
| } | |
| } | |
| interface B38257037_I2 extends B38257037_I1 { | |
| @Override | |
| default Double getNumber() { | |
| return new Double(2.3); | |
| } | |
| } | |
| static class B38257037_C implements B38257037_I2 { | |
| } | |
| /** | |
| * Check that bridges are generated. | |
| */ | |
| static class B38257037 { | |
| private B38257037_C c = new B38257037_C(); | |
| public Double test1() { | |
| return c.getNumber(); | |
| } | |
| public Number test2() { | |
| return ((B38257037_I1) c).getNumber(); | |
| } | |
| public static void test() { | |
| B38257037 l = new B38257037(); | |
| if (l.test1() == 2.3) { | |
| System.out.println("Check 1: OK"); | |
| } else { | |
| System.out.println("Check 1: NOT OK"); | |
| } | |
| if (l.test2().equals(new Double(2.3))) { | |
| System.out.println("Check 2: OK"); | |
| } else { | |
| System.out.println("Check 2: NOT OK"); | |
| } | |
| } | |
| } | |
| interface B38306708_I { | |
| class $CC{ | |
| static void print() { | |
| System.out.println("$CC"); | |
| } | |
| } | |
| default String m() { | |
| return "ITop.m()"; | |
| } | |
| } | |
| static class B38306708 { | |
| public static void test() { | |
| B38306708_I.$CC.print(); | |
| } | |
| } | |
| interface B38308515_I { | |
| default String m() { | |
| return "m instance"; | |
| } | |
| static String m(B38308515_I i) { | |
| return "m static"; | |
| } | |
| } | |
| static class B38308515_C implements B38308515_I { | |
| } | |
| static class B38308515 { | |
| static void test() { | |
| B38308515_C c = new B38308515_C(); | |
| System.out.println(c.m()); | |
| System.out.println(B38308515_I.m(c)); | |
| } | |
| } | |
| static class B38302860 { | |
| @SomeAnnotation(1) | |
| private interface AnnotatedInterface { | |
| @SomeAnnotation(2) | |
| void annotatedAbstractMethod(); | |
| @SomeAnnotation(3) | |
| default void annotatedDefaultMethod() { | |
| } | |
| @SomeAnnotation(4) | |
| static void annotatedStaticMethod() { | |
| // Bogus body to be included into the root set: if interface desugaring is on, root set | |
| // builder will skip marking methods without code. | |
| synchronized (AnnotatedInterface.class) { | |
| } | |
| } | |
| } | |
| @Retention(value = RetentionPolicy.RUNTIME) | |
| private @interface SomeAnnotation { | |
| int value(); | |
| } | |
| private static boolean checkAnnotationValue(Annotation[] annotations, int value) { | |
| if (annotations.length != 1) { | |
| return false; | |
| } | |
| return annotations[0] instanceof SomeAnnotation | |
| && ((SomeAnnotation) annotations[0]).value() == value; | |
| } | |
| @SuppressWarnings("unchecked") | |
| static void test() throws Exception { | |
| if (checkAnnotationValue(AnnotatedInterface.class.getAnnotations(), 1)) { | |
| System.out.println("Check 1: OK"); | |
| } else { | |
| System.out.println("Check 1: NOT OK"); | |
| } | |
| if (checkAnnotationValue( | |
| AnnotatedInterface.class.getMethod("annotatedAbstractMethod").getAnnotations(), 2)) { | |
| System.out.println("Check 2: OK"); | |
| } else { | |
| System.out.println("Check 2: NOT OK"); | |
| } | |
| if (checkAnnotationValue( | |
| AnnotatedInterface.class.getMethod("annotatedDefaultMethod").getAnnotations(), 3)) { | |
| System.out.println("Check 3: OK"); | |
| } else { | |
| System.out.println("Check 3: NOT OK"); | |
| } | |
| // I don't know how to keep this method moved to the companion class | |
| // without the direct call. | |
| AnnotatedInterface.annotatedStaticMethod(); | |
| if (checkAnnotationValue( | |
| getCompanionClassOrInterface().getMethod("annotatedStaticMethod").getAnnotations(), 4)) { | |
| System.out.println("Check 4: OK"); | |
| } else { | |
| System.out.println("Check 4: NOT OK"); | |
| } | |
| } | |
| private static Class getCompanionClassOrInterface() { | |
| try { | |
| return Class.forName("lambdadesugaringnplus." | |
| + "LambdasWithStaticAndDefaultMethods$B38302860$AnnotatedInterface$-CC"); | |
| } catch (Exception e) { | |
| return AnnotatedInterface.class; | |
| } | |
| } | |
| } | |
| static class B62168701 { | |
| interface I extends Serializable { | |
| String getValue(); | |
| } | |
| interface J { | |
| static void dump() { | |
| I i = () -> "B62168701 -- OK"; | |
| System.out.println(i.getValue()); | |
| } | |
| } | |
| static void test() { | |
| J.dump(); | |
| } | |
| } | |
| static void z(Z p) { | |
| System.out.println(p.foo(null)); | |
| } | |
| static void g(G<String[]> g) { | |
| StringBuilder builder = new StringBuilder("{"); | |
| String sep = ""; | |
| for (String s : g.foo(new String[] { "Arg0", "Arg1", "Arg2" })) { | |
| builder.append(sep).append(s); | |
| sep = ", "; | |
| } | |
| builder.append("}"); | |
| System.out.println(builder.toString()); | |
| } | |
| interface SuperChain { | |
| default String iMain() { | |
| return "SuperChain::iMain()"; | |
| } | |
| } | |
| interface SuperChainDerived extends SuperChain { | |
| default String iMain() { | |
| return "SuperChainDerived::iMain(" + SuperChain.super.iMain() + ")"; | |
| } | |
| } | |
| interface OtherSuperChain { | |
| default String iMain() { | |
| return "OtherSuperChain::iMain()"; | |
| } | |
| } | |
| static class ClassWithSuperChain implements SuperChainDerived, OtherSuperChain { | |
| public String iMain() { | |
| return "ClassWithSuperChain::iMain(" + SuperChainDerived.super.iMain() + ")" + iMainImpl(); | |
| } | |
| public String iMainImpl() { | |
| return "ClassWithSuperChain::iMain(" + SuperChainDerived.super.iMain() + | |
| " + " + OtherSuperChain.super.iMain() + ")"; | |
| } | |
| } | |
| public static void main(String[] args) throws Exception { | |
| C c = new C(); | |
| I i = c; | |
| c.iRegular(); | |
| c.iDefault(); | |
| c.iDefaultOverridden(); | |
| I.iStatic(); | |
| i.iRegular(); | |
| i.iDefault(); | |
| i.iDefaultOverridden(); | |
| p(i.stateless()::iRegular); | |
| p(i.stateful()::iRegular); | |
| g(a -> a); | |
| g(a -> { | |
| int size = a.length; | |
| for (int x = 0; x < size / 2; x++) { | |
| String t = a[x]; | |
| a[x] = a[size - 1 - x]; | |
| a[size - 1 - x] = t; | |
| } | |
| return a; | |
| }); | |
| p(c::iRegular); | |
| p(c::iDefault); | |
| p(c::iDefaultOverridden); | |
| p(I::iStatic); | |
| p(i::iRegular); | |
| p(i::iDefault); | |
| p(i::iDefaultOverridden); | |
| II ii = i::iRegular; | |
| p(II::iStatic); | |
| p(ii::iRegular); | |
| p(ii::iDefault); | |
| p(ii::iDefaultOverridden); | |
| z(s -> "From Interface With Bridges"); | |
| System.out.println(new ClassWithSuperChain().iMain()); | |
| ClassWithDefaultPackagePrivate c2 = new ClassWithDefaultPackagePrivate(); | |
| InterfaceWithDefaultPackagePrivate i2 = c2; | |
| c2.defaultFoo(); | |
| i2.defaultFoo(); | |
| InterfaceWithDefaultPackagePrivate.staticFoo(); | |
| p(c2::defaultFoo); | |
| p(i2::defaultFoo); | |
| p(InterfaceWithDefaultPackagePrivate::staticFoo); | |
| p(c2.lambda()::foo); | |
| B38257361.test(); | |
| B38257037.test(); | |
| B38306708.test(); | |
| B38308515.test(); | |
| B38302860.test(); | |
| B62168701.test(); | |
| B78901754.test(); | |
| } | |
| } |