|  | // 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(); | 
|  | } | 
|  | } |