Skip to content

Commit b735954

Browse files
committed
Java frontend: support lambdas that implicitly box to Object
This broadens our support for lambdas with implicit boxing/unboxing conversions to include those that use a method-reference to a method with type Object -> x to satisfy a functional interface of type primitive -> x (requiring boxing the parameter and then upcasting to Object), or a method with type x -> primitive satisfying an interface of type x -> Object (requiring the same conversion on the return value).
1 parent 5ec200c commit b735954

8 files changed

+50
-6
lines changed
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
public class BoxingWithOtherConversions {
2+
3+
interface ObjectToObject {
4+
Object accept(Object o);
5+
}
6+
7+
interface IntToObject {
8+
Object accept(int i);
9+
}
10+
11+
// Check we can narrow a parameter type down to a primitive
12+
// which should be boxed and then upcast to Object by the
13+
// generated lambda:
14+
public static void testNarrowParameterTypeToPrimitive() {
15+
ObjectToObject o2o = i -> ((Integer)i) + 1;
16+
IntToObject i2o = o2o::accept;
17+
assert o2o.accept(1).equals(2);
18+
assert i2o.accept(1).equals(2);
19+
assert false;
20+
}
21+
22+
interface ObjectToInt {
23+
int accept(Object o);
24+
}
25+
26+
public static void testBroadenReturnTypeToObject() {
27+
ObjectToInt o2i = o -> ((Integer)o).intValue() + 1;
28+
ObjectToObject o2o = o2i::accept;
29+
assert o2o.accept(1).equals(2);
30+
assert o2i.accept(1) == 2;
31+
assert false;
32+
}
33+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
BoxingWithOtherConversions
3+
--function BoxingWithOtherConversions.testBroadenReturnTypeToObject --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar`
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
\[java::BoxingWithOtherConversions\.testBroadenReturnTypeToObject:\(\)V.assertion\.1\] line 29 assertion at file BoxingWithOtherConversions\.java line 29 function java::BoxingWithOtherConversions\.testBroadenReturnTypeToObject:\(\)V bytecode-index 21: SUCCESS
7+
\[java::BoxingWithOtherConversions\.testBroadenReturnTypeToObject:\(\)V.assertion\.2\] line 30 assertion at file BoxingWithOtherConversions\.java line 30 function java::BoxingWithOtherConversions\.testBroadenReturnTypeToObject:\(\)V bytecode-index 33: SUCCESS
8+
\[java::BoxingWithOtherConversions\.testBroadenReturnTypeToObject:\(\)V.assertion\.3\] line 31 assertion at file BoxingWithOtherConversions\.java line 31 function java::BoxingWithOtherConversions\.testBroadenReturnTypeToObject:\(\)V bytecode-index 39: FAILURE
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
BoxingWithOtherConversions
3+
--function BoxingWithOtherConversions.testNarrowParameterTypeToPrimitive --cp `../../../../scripts/format_classpath.sh . ../../../lib/java-models-library/target/core-models.jar`
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
\[java::BoxingWithOtherConversions\.testNarrowParameterTypeToPrimitive:\(\)V.assertion.1\] line 17 assertion at file BoxingWithOtherConversions\.java line 17 function java::BoxingWithOtherConversions\.testNarrowParameterTypeToPrimitive:\(\)V bytecode-index 21: SUCCESS
7+
\[java::BoxingWithOtherConversions\.testNarrowParameterTypeToPrimitive:\(\)V.assertion.2\] line 18 assertion at file BoxingWithOtherConversions\.java line 18 function java::BoxingWithOtherConversions\.testNarrowParameterTypeToPrimitive:\(\)V bytecode-index 34: SUCCESS
8+
\[java::BoxingWithOtherConversions\.testNarrowParameterTypeToPrimitive:\(\)V.assertion.3\] line 19 assertion at file BoxingWithOtherConversions\.java line 19 function java::BoxingWithOtherConversions\.testNarrowParameterTypeToPrimitive:\(\)V bytecode-index 40: FAILURE

jbmc/src/java_bytecode/lambda_synthesis.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -662,17 +662,12 @@ exprt adjust_type_if_necessary(
662662
}
663663
else
664664
{
665-
const irep_idt &boxed_type_id =
666-
to_struct_tag_type(required_type.subtype()).get_identifier();
667665
const auto *primitive_type_info =
668666
get_java_primitive_type_info(original_type);
669667
INVARIANT(
670668
primitive_type_info != nullptr,
671669
"A Java non-pointer type involved in a type disagreement should"
672670
" be a primitive");
673-
INVARIANT(
674-
boxed_type_id == primitive_type_info->boxed_type_name,
675-
"Boxed types are only convertable to their corresponding unboxed type");
676671

677672
symbol_exprt fresh_local = create_and_declare_local(
678673
function_id, role + "_boxed", required_type, symbol_table, code_block);
@@ -682,7 +677,7 @@ exprt adjust_type_if_necessary(
682677
code_block.add(code_function_callt{
683678
fresh_local, boxed_type_factory_method.symbol_expr(), {expr}});
684679

685-
return std::move(fresh_local);
680+
return typecast_exprt::conditional_cast(fresh_local, required_type);
686681
}
687682
}
688683

0 commit comments

Comments
 (0)