Skip to content

Commit bdc3666

Browse files
committed
Fixes scala#15736
Box native instantiated method return type if sam method return type is not a primitive type to satisfy conditions specified in https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/LambdaMetafactory.html Condition is not enforced by JVM but by Android ART.
1 parent afb4806 commit bdc3666

File tree

1 file changed

+23
-3
lines changed

1 file changed

+23
-3
lines changed

compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,8 +1773,6 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
17731773
val returnUnit = lambdaTarget.info.resultType.typeSymbol == defn.UnitClass
17741774
val functionalInterfaceDesc: String = generatedType.descriptor
17751775
val desc = capturedParamsTypes.map(tpe => toTypeKind(tpe)).mkString(("("), "", ")") + functionalInterfaceDesc
1776-
// TODO specialization
1777-
val instantiatedMethodType = new MethodBType(lambdaParamTypes.map(p => toTypeKind(p)), toTypeKind(lambdaTarget.info.resultType)).toASMType
17781776

17791777
val samMethod = atPhase(erasurePhase) {
17801778
val samMethods = toDenot(functionalInterface).info.possibleSamMethods.toList
@@ -1787,7 +1785,29 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
17871785
}
17881786

17891787
val methodName = samMethod.javaSimpleName
1790-
val samMethodType = asmMethodType(samMethod).toASMType
1788+
val samMethodBType = asmMethodType(samMethod)
1789+
val samMethodType = samMethodBType.toASMType
1790+
1791+
def boxInstantiated(instantiatedType: BType, samType: BType): BType =
1792+
if(!samType.isPrimitive && instantiatedType.isPrimitive)
1793+
boxedClassOfPrimitive(instantiatedType.asPrimitiveBType)
1794+
else instantiatedType
1795+
// TODO specialization
1796+
val instantiatedMethodBType = new MethodBType(
1797+
lambdaParamTypes.map(p => toTypeKind(p)),
1798+
boxInstantiated(toTypeKind(lambdaTarget.info.resultType), samMethodBType.returnType)
1799+
)
1800+
1801+
// check that types are equal for parameters and return type as required by spec of altMetafactory
1802+
def checkInstantiated(a: BType, b: BType): Boolean =
1803+
(!a.isPrimitive && !b.isPrimitive) || (a.isPrimitive && b.isPrimitive && a == b)
1804+
assert(
1805+
samMethodBType.argumentTypes.zip(instantiatedMethodBType.argumentTypes).forall(checkInstantiated) && checkInstantiated(samMethodBType.returnType,
1806+
instantiatedMethodBType.returnType), s"Primitive types must be equal: ${samMethodBType} vs. $instantiatedMethodBType"
1807+
)
1808+
1809+
val instantiatedMethodType = instantiatedMethodBType.toASMType
1810+
17911811
// scala/bug#10334: make sure that a lambda object for `T => U` has a method `apply(T)U`, not only the `(Object)Object`
17921812
// version. Using the lambda a structural type `{def apply(t: T): U}` causes a reflective lookup for this method.
17931813
val needsGenericBridge = samMethodType != instantiatedMethodType

0 commit comments

Comments
 (0)