Skip to content

Commit 4d101af

Browse files
committed
Support for lambdas with marker interfaces
Fixes #62
1 parent bc192b5 commit 4d101af

File tree

4 files changed

+81
-1
lines changed

4 files changed

+81
-1
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,11 @@ optimizations to that mechanism may break Retrolambda.
208208
Version History
209209
---------------
210210

211+
### Upcoming
212+
213+
- Support for lambdas with marker interfaces
214+
([Issue #62](https://github.com/orfjackal/retrolambda/issues/62))
215+
211216
### Retrolambda 2.0.4 (2015-07-08)
212217

213218
- Fixed a compile error when calling default methods from another module

end-to-end-tests/src/test/java/net/orfjackal/retrolambda/test/LambdaTest.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,16 @@ public interface LambdaConstant {
9999
Callable<String> LAMBDA = () -> "foo";
100100
}
101101

102+
@Test
103+
public void lambdas_with_marker_interfaces_due_to_intersection_types() throws Exception {
104+
// We must use something other than java.io.Serializable as the marker interface,
105+
// because serializable lambdas are signified by a flag to LambdaMetafactory.altMetafactory
106+
Callable<String> lambda = (Callable<String> & Cloneable) () -> "foo";
107+
108+
assertThat(lambda, is(instanceOf(Cloneable.class)));
109+
assertThat(lambda.call(), is("foo"));
110+
}
111+
102112
@Test
103113
public void method_references_to_virtual_methods() throws Exception {
104114
String foo = "foo";

retrolambda/src/main/java/net/orfjackal/retrolambda/lambdas/Types.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,14 @@ public class Types {
1414

1515
public static Object asmToJdkType(Object arg, ClassLoader classLoader, MethodHandles.Lookup caller) throws Exception {
1616
if (arg instanceof Type) {
17-
return toMethodType((Type) arg, classLoader);
17+
Type type = (Type) arg;
18+
if (type.getSort() == Type.METHOD) {
19+
return toMethodType(type, classLoader);
20+
} else if (type.getSort() == Type.OBJECT) {
21+
return toClass(type, classLoader);
22+
} else {
23+
throw new IllegalArgumentException("Unsupported type: " + type);
24+
}
1825
} else if (arg instanceof Handle) {
1926
return toMethodHandle((Handle) arg, classLoader, caller);
2027
} else {
@@ -26,6 +33,10 @@ public static MethodType toMethodType(Type type, ClassLoader classLoader) {
2633
return MethodType.fromMethodDescriptorString(type.getInternalName(), classLoader);
2734
}
2835

36+
private static Class<?> toClass(Type type, ClassLoader classLoader) throws ClassNotFoundException {
37+
return classLoader.loadClass(type.getInternalName().replace('/', '.'));
38+
}
39+
2940
public static MethodHandle toMethodHandle(Handle handle, ClassLoader classLoader, MethodHandles.Lookup lookup) throws Exception {
3041
MethodType type = MethodType.fromMethodDescriptorString(handle.getDesc(), classLoader);
3142
Class<?> owner = classLoader.loadClass(handle.getOwner().replace('/', '.'));
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright © 2013-2015 Esko Luontola <www.orfjackal.net>
2+
// This software is released under the Apache License 2.0.
3+
// The license text is at http://www.apache.org/licenses/LICENSE-2.0
4+
5+
package net.orfjackal.retrolambda.lambdas;
6+
7+
import org.junit.Test;
8+
import org.objectweb.asm.*;
9+
10+
import java.lang.invoke.*;
11+
import java.util.function.Predicate;
12+
13+
import static net.orfjackal.retrolambda.lambdas.Types.asmToJdkType;
14+
import static org.hamcrest.MatcherAssert.assertThat;
15+
import static org.hamcrest.Matchers.*;
16+
17+
@SuppressWarnings("UnnecessaryLocalVariable")
18+
public class TypesTest {
19+
20+
private ClassLoader classLoader = getClass().getClassLoader();
21+
private MethodHandles.Lookup lookup = MethodHandles.lookup();
22+
23+
@Test
24+
public void asmToJdkType_MethodType() throws Exception {
25+
Type input = Type.getMethodType("(I)Ljava/util/function/Predicate;");
26+
MethodType output = MethodType.methodType(Predicate.class, int.class);
27+
28+
assertThat(asmToJdkType(input, classLoader, lookup), is(output));
29+
}
30+
31+
@Test
32+
public void asmToJdkType_MethodHandle() throws Exception {
33+
Handle input = new Handle(Opcodes.H_INVOKESTATIC, "java/lang/String", "valueOf", "(I)Ljava/lang/String;");
34+
MethodHandle output = lookup.findStatic(String.class, "valueOf", MethodType.methodType(String.class, int.class));
35+
36+
assertThat(asmToJdkType(input, classLoader, lookup).toString(), is(output.toString()));
37+
}
38+
39+
@Test
40+
public void asmToJdkType_Class() throws Exception {
41+
Type input = Type.getType(String.class);
42+
Class<?> output = String.class;
43+
44+
assertThat(asmToJdkType(input, classLoader, lookup), is(equalTo(output)));
45+
}
46+
47+
@Test
48+
public void asmToJdkType_everything_else() throws Exception {
49+
String input = "foo";
50+
String output = input;
51+
52+
assertThat(asmToJdkType(input, classLoader, lookup), is(output));
53+
}
54+
}

0 commit comments

Comments
 (0)