blob: 910f2c45cdbb9f3ff918ae107935b2a4bdfe719d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.core.tests.compiler.regression;
import junit.framework.Test;
public class LambdaRegressionTest extends AbstractRegressionTest {
static {
// TESTS_NAMES = new String[] { "test001"};
// TESTS_NUMBERS = new int[] { 50 };
// TESTS_RANGE = new int[] { 11, -1 };
}
public LambdaRegressionTest(String name) {
super(name);
}
public static Test suite() {
return buildMinimalComplianceTestSuite(testClass(), F_1_8);
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=446317, java.lang.VerifyError: Bad type on operand stack with Lambdas and/or inner classes
public void test001() {
this.runConformTest(
new String[] {
"X.java",
"import java.util.HashMap;\n" +
"import java.util.Map;\n" +
"import java.util.function.Function;\n" +
"public class X {\n" +
" public static void main(String[] args) {\n" +
" new X().run();\n" +
" }\n" +
" public void run() {\n" +
" class Inner {\n" +
" public Inner() {\n" +
" System.out.println(\"miep\");\n" +
" }\n" +
" }\n" +
" Map<String, Inner> map = new HashMap<>();\n" +
" Function<String, Inner> function = (name) -> {\n" +
" Inner i = map.get(name);\n" +
" if (i == null) {\n" +
" i = new Inner();\n" +
" map.put(name, i);\n" +
" }\n" +
" return i;\n" +
"\n" +
" };\n" +
" function.apply(\"test\");\n" +
" }\n" +
"}\n",
},
"miep"
);
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=446317, java.lang.VerifyError: Bad type on operand stack with Lambdas and/or inner classes
public void test002() {
this.runNegativeTest(
new String[] {
"X.java",
"import java.util.function.Consumer;\n" +
"@SuppressWarnings(\"all\")\n" +
"public class X {\n" +
" private final String text = \"Bug?\";\n" +
" public static void main(String[] args) {\n" +
" new X().doIt();\n" +
" }\n" +
" private void doIt() {\n" +
" new Sub();\n" +
" }\n" +
" private class Super<T> {\n" +
" public Super(Consumer<T> consumer) {\n" +
" }\n" +
" }\n" +
" private class Sub extends Super<String> {\n" +
" public Sub() {\n" +
" super(s -> System.out.println(text));\n" +
" // super(s -> System.out.println(\"miep\"));\n" +
" }\n" +
" }\n" +
"}\n",
},
"----------\n" +
"1. ERROR in X.java (at line 17)\n" +
" super(s -> System.out.println(text));\n" +
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
"Cannot refer to \'this\' nor \'super\' while explicitly invoking a constructor\n" +
"----------\n"
);
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=446317, java.lang.VerifyError: Bad type on operand stack with Lambdas and/or inner classes
public void test003() {
this.runNegativeTest(
new String[] {
"X.java",
"import java.util.function.Consumer;\n" +
"@SuppressWarnings(\"all\")\n" +
"public class X {\n" +
" private final String text = \"Bug?\";\n" +
" public static void main(String[] args) {\n" +
" new X().doIt();\n" +
" }\n" +
" private void doIt() {\n" +
" new Sub();\n" +
" }\n" +
" private class Super<T> {\n" +
" public Super(Consumer<T> consumer) {\n" +
" }\n" +
" }\n" +
" private class Sub extends Super<String> {\n" +
" public Sub() {\n" +
" super(s -> System.out.println(\"miep\"));\n" +
" }\n" +
" }\n" +
"}\n",
},
""
);
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=446317, java.lang.VerifyError: Bad type on operand stack with Lambdas and/or inner classes
public void test004() {
this.runConformTest(
new String[] {
"Y.java",
"import java.util.function.Supplier;\n" +
"class E {\n" +
" E(Supplier<Object> factory) { }\n" +
"}\n" +
"public class Y extends E {\n" +
" Y() {\n" +
" super( () -> {\n" +
" class Z extends E {\n" +
" Z() {\n" +
" super(() -> new Object());\n" +
" }\n" +
" }\n" +
" return null;\n" +
" });\n" +
" }\n" +
" public static void main(String[] args) {\n" +
" new Y();\n" +
" }\n" +
"}"
});
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=448724, [1.8] [compiler] Wrong resolution of overloaded method when irrelevant type parameter is present and lambda is used as parameter
public void test448724() {
this.runConformTest(
new String[] {
"X.java",
"import java.util.concurrent.Callable;\n" +
"public class X {\n" +
" public void mismatchRunnableCallable() throws Exception {\n" +
" //Resolves to case1(Runnable) method invocation; lambda with block\n" +
" case1(() -> {\"abc\".length();});\n" +
" //Resolves to case1(Callable) method invocation, resulting in type mismatch; block removed - lambda with expression\n" +
" case1(() -> \"abc\".length());\n" +
" }\n" +
" public void noSuchMismatch() throws Exception {\n" +
" //no difference to case1 \n" +
" case2(() -> {\"abc\".length();});\n" +
" //the only difference to case 1 is the missing irrelevant <T> type parameter. Properly resolves to case2(Runnable) here\n" +
" case2(() -> \"abc\".length());\n" +
" }\n" +
" public void case1(final Runnable r) {\n" +
" System.out.println(\"case1: Runnable\");\n" +
" }\n" +
" public <T> void case1(Callable<Boolean> c) {\n" +
" System.out.println(\"case1: Callable\");\n" +
" }\n" +
" public void case2(final Runnable supplier) {\n" +
" System.out.println(\"case2: Runnable\");\n" +
" }\n" +
" public void case2(Callable<Boolean> conditionEvaluator) {\n" +
" System.out.println(\"case2: Callable\");\n" +
" }\n" +
" public static void main(String[] args) throws Exception {\n" +
" new X().mismatchRunnableCallable();\n" +
" new X().noSuchMismatch();\n" +
" }\n" +
"}\n"
},
"case1: Runnable\n" +
"case1: Runnable\n" +
"case2: Runnable\n" +
"case2: Runnable");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=447767, [1.8][compiler] Spurious method not applicable error due to interaction between overload resolution and type inference
public void test447767() {
this.runConformTest(
new String[] {
"X.java",
"interface I<T, U, V> {\n" +
" T goo(U u, V v);\n" +
"}\n" +
"public class X {\n" +
" static <T, U, V> T foo(T t, U u, V v) {\n" +
" System.out.println(\"Wrong!\");\n" +
" return null;\n" +
" }\n" +
" static <T, U, V> V foo(T t, U u, I<T, U, V> i) {\n" +
" System.out.println(\"Right!\");\n" +
" return null;\n" +
" }\n" +
" public static void main(String[] args) {\n" +
" String s = goo(foo(\"String\", \"String\", (u, v) -> v));\n" +
" }\n" +
" static <T> T goo(T t) {\n" +
" return t; \n" +
" }\n" +
"}\n"
},
"Right!");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=447767, [1.8][compiler] Spurious method not applicable error due to interaction between overload resolution and type inference
public void test447767a() {
this.runNegativeTest(
new String[] {
"X.java",
"interface I<T, U, V> {\n" +
" T goo(U u, V v);\n" +
"}\n" +
"public class X {\n" +
" static <T, U, V> T foo(T t, U u, I<T, U, V> i) {\n" +
" return null;\n" +
" }\n" +
" public static void main(String[] args) {\n" +
" String s = goo(foo(\"String\", \"String\", (u, v) -> v));\n" +
" }\n" +
" static <T> T goo(T t) {\n" +
" return t; \n" +
" }\n" +
"}\n"
},
"----------\n" +
"1. ERROR in X.java (at line 9)\n" +
" String s = goo(foo(\"String\", \"String\", (u, v) -> v));\n" +
" ^\n" +
"Type mismatch: cannot convert from Object to String\n" +
"----------\n");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=447767, [1.8][compiler] Spurious method not applicable error due to interaction between overload resolution and type inference
public void test447767b() {
this.runConformTest(
new String[] {
"X.java",
"interface I<T, U, V> {\n" +
" T goo(U u, V v);\n" +
"}\n" +
"public class X {\n" +
" static String goo(String s, String s2) {\n" +
" return null;\n" +
" }\n" +
" static <T, U, V> V foo(T t, U u, I<T, U, V> i) {\n" +
" System.out.println(\"Right!\");\n" +
" return null;\n" +
" }\n" +
" public static void main(String[] args) {\n" +
" String s = goo(foo(\"String\", \"String\", X::goo));\n" +
" }\n" +
" static <T> T goo(T t) {\n" +
" return t; \n" +
" }\n" +
"}\n"
},
"Right!");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=447767, [1.8][compiler] Spurious method not applicable error due to interaction between overload resolution and type inference
public void test447767c() {
this.runConformTest(
new String[] {
"X.java",
"interface I<T, U, V> {\n" +
" T goo(U u, V v);\n" +
"}\n" +
"public class X {\n" +
" static String goo(String s, String s2) {\n" +
" return null;\n" +
" }\n" +
" static <T, U, V> T foo(T t, U u, V v) {\n" +
" System.out.println(\"Wrong!\");\n" +
" return null;\n" +
" }\n" +
" static <T, U, V> V foo(T t, U u, I<T, U, V> i) {\n" +
" System.out.println(\"Right!\");\n" +
" return null;\n" +
" }\n" +
" public static void main(String[] args) {\n" +
" String s = goo(foo(\"String\", \"String\", X::goo));\n" +
" }\n" +
" static <T> T goo(T t) {\n" +
" return t; \n" +
" }\n" +
"}\n"
},
"Right!");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=447767, [1.8][compiler] Spurious method not applicable error due to interaction between overload resolution and type inference
public void test447767d() {
this.runConformTest(
new String[] {
"X.java",
"interface I<T, U, V> {\n" +
" T goo(U u, V v);\n" +
"}\n" +
"public class X {\n" +
" static String goo(String s, String s2) {\n" +
" return null;\n" +
" }\n" +
" static <T, U, V> T foo(T t, U u, V v) {\n" +
" System.out.println(\"Wrong!\");\n" +
" return null;\n" +
" }\n" +
" static <T, U, V> V foo(T t, U u, I<T, U, V> i) {\n" +
" System.out.println(\"Right!\");\n" +
" return null;\n" +
" }\n" +
" public static void main(String[] args) {\n" +
" String s = goo(foo(\"String\", \"String\", X::goo));\n" +
" }\n" +
" static <T> T goo(T t) {\n" +
" return t; \n" +
" }\n" +
"}\n"
},
"Right!");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=449410, [1.8][compiler] Eclipse java compiler does not detect a bad return type in lambda expression
public void test449410() {
this.runNegativeTest(
new String[] {
"X.java",
"import java.util.Collections;\n" +
"public class X {\n" +
" public static void main(String[] args) {\n" +
" Collections.emptyMap()\n" +
" .entrySet()\n" +
" .forEach(entry -> test() ? bad() : returnType());\n" +
" }\n" +
" private static boolean test() {\n" +
" return (System.currentTimeMillis() & 0x1) == 0;\n" +
" }\n" +
" private static void returnType() {\n" +
" }\n" +
" private static void bad() {\n" +
" }\n" +
"}\n"
},
"----------\n" +
"1. ERROR in X.java (at line 6)\n" +
" .forEach(entry -> test() ? bad() : returnType());\n" +
" ^^^^^^^\n" +
"The method forEach(Consumer<? super Map.Entry<Object,Object>>) in the type Iterable<Map.Entry<Object,Object>> is not applicable for the arguments ((<no type> entry) -> {})\n" +
"----------\n");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=449824, [1.8] Difference in behaviour with method references and lambdas
// Captures present behavior - may not be correct.
public void test449824() {
this.runNegativeTest(
new String[] {
"X.java",
"public class X {\n" +
" public static void main(String[] args) {\n" +
" Concrete<Target> fl = new Concrete<Target>();\n" +
" fl.call(each -> each.doSomething()); // fails\n" +
" fl.call((Target each) -> each.doSomething()); // fails\n" +
" fl.call(Target::doSomething); // succeeds in Eclipse 4.5M3 and 4.4.1\n" +
" // but fails in Java 8 1.8.0_11\n" +
" }\n" +
" public static class Target {\n" +
" public void doSomething() {\n" +
" }\n" +
" }\n" +
" public static class Concrete<T> implements Left<T>, Right<T> {\n" +
" public void call(RightHand<? super T> p) {\n" +
" }\n" +
" }\n" +
" public interface Left<T> {\n" +
" default void call(LeftHand<? super T> p) {\n" +
" }\n" +
" }\n" +
" public interface LeftHand<T> {\n" +
" public void left(T t);\n" +
" }\n" +
" public interface Right<T> {\n" +
" public void call(RightHand<? super T> p);\n" +
" }\n" +
" public interface RightHand<T> {\n" +
" public void right(T t);\n" +
" }\n" +
"}\n"
},
"----------\n" +
"1. ERROR in X.java (at line 4)\n" +
" fl.call(each -> each.doSomething()); // fails\n" +
" ^^^^\n" +
"The method call(X.RightHand<? super X.Target>) is ambiguous for the type X.Concrete<X.Target>\n" +
"----------\n");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=448954, [1.8][compiler] Suspect error: "The method foo(String, String, X::goo) is undefined for the type X"
public void test448954() {
this.runConformTest(
new String[] {
"X.java",
"interface I<T, U, V> {\n" +
" T goo(U u, V v);\n" +
"}\n" +
"interface J {\n" +
" void foo();\n" +
"}\n" +
"public class X {\n" +
" static String goo(String s, String s2) {\n" +
" return null;\n" +
" }\n" +
" static <T, U, V> T foo(T t, U u, J j) {\n" +
" System.out.println(\"Wrong!\");\n" +
" return null;\n" +
" }\n" +
" static <T, U, V> V foo(T t, U u, I<T, U, V> i) {\n" +
" System.out.println(\"Right!\");\n" +
" return null;\n" +
" }\n" +
" public static void main(String[] args) {\n" +
" String s = goo(foo(\"String\", \"String\", X::goo));\n" +
" }\n" +
" static <T> T goo(T t) {\n" +
" return t;\n" +
" }\n" +
"}\n"
},
"Right!");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=450380, [1.8][compiler] NPE in Scope.getExactConstructor(..) for bad constructor reference
public void test450380() {
this.runNegativeTest(
new String[] {
"X.java",
"import java.util.ArrayList;\n" +
"import java.util.function.IntFunction;\n" +
"public class X {\n" +
" IntFunction<ArrayList<String>> noo() {\n" +
" return System::new;\n" +
" }\n" +
"}\n"
},
"----------\n" +
"1. ERROR in X.java (at line 5)\n" +
" return System::new;\n" +
" ^^^^^^^^^^^\n" +
"The type System does not define System(int) that is applicable here\n" +
"----------\n");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=450604, [1.8] CCE at InferenceContext18.getParameter line 1377
public void test450604() {
this.runNegativeTest(
new String[] {
"X.java",
"import java.io.IOException;\n" +
"import java.util.List;\n" +
"import java.util.function.Function;\n" +
"public class X<T, E extends Exception> {\n" +
" public static <T> List<T> of(T one) { return null; }\n" +
" public @SafeVarargs static <T> List<T> of(T... items) { return null; }\n" +
" public static void printDependencyLoops() throws IOException {\n" +
" Function<? super String, ? extends List<String>> mapping = X::of;\n" +
" }\n" +
"}\n"
},
"");
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=450604, [1.8] CCE at InferenceContext18.getParameter line 1377
public void test450604a() {
this.runConformTest(
new String[] {
"X.java",
"import java.util.List;\n" +
"public class X {\n" +
" public static <T> List<T> of() { return null; }\n" +
" public static @SafeVarargs <T> List<T> of(T... values) { return null; }\n" +
" static void walkAll() {\n" +
" X.<String> of();\n" +
" }\n" +
"}\n"
});
}
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=451677, [1.8][compiler] missing type inference
public void _test451677() {
this.runConformTest(
new String[] {
"X.java",
"import java.util.ArrayList;\n" +
"import java.util.function.Function;\n" +
"public class X {\n" +
" public static void test() {\n" +
" operationOnCreated(create(123, size -> new ArrayList<Integer>(size)), l -> l.size()); // works with: (ArrayList<Integer> l) -> l.size()\n" +
" }\n" +
" public static <R, A> R create(A arg, Function<A, R> factory) {\n" +
" return factory.apply(arg);\n" +
" }\n" +
" public static <R, A> R operationOnCreated(A created, Function<A, R> function) {\n" +
" return function.apply(created);\n" +
" }\n" +
"}\n"
});
}
public static Class testClass() {
return LambdaRegressionTest.class;
}
}