@@ -1414,7 +1414,7 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
14141414    def  genLoadTry (tree : Try ):  BType 
14151415
14161416    def  genInvokeDynamicLambda (ctor : Symbol , lambdaTarget : Symbol , environmentSize : Int , functionalInterface : Symbol ):  BType  =  {
1417-       import  java .lang .invoke .LambdaMetafactory .FLAG_SERIALIZABLE 
1417+       import  java .lang .invoke .LambdaMetafactory .{ FLAG_BRIDGES ,  FLAG_SERIALIZABLE } 
14181418
14191419      report.debuglog(s " Using invokedynamic rather than `new  ${ctor.owner}` " )
14201420      val  generatedType  =  classBTypeFromSymbol(functionalInterface)
@@ -1445,9 +1445,9 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
14451445      val  functionalInterfaceDesc :  String  =  generatedType.descriptor
14461446      val  desc  =  capturedParamsTypes.map(tpe =>  toTypeKind(tpe)).mkString((" (" " " " )" +  functionalInterfaceDesc
14471447      //  TODO specialization
1448-       val  constrainedType  =  new  MethodBType (lambdaParamTypes.map(p =>  toTypeKind(p)), toTypeKind(lambdaTarget.info.resultType)).toASMType
1448+       val  instantiatedMethodType  =  new  MethodBType (lambdaParamTypes.map(p =>  toTypeKind(p)), toTypeKind(lambdaTarget.info.resultType)).toASMType
14491449
1450-       val  abstractMethod  =  atPhase(erasurePhase) {
1450+       val  samMethod  =  atPhase(erasurePhase) {
14511451        val  samMethods  =  toDenot(functionalInterface).info.possibleSamMethods.toList
14521452        samMethods match  {
14531453          case  x ::  Nil  =>  x.symbol
@@ -1457,21 +1457,40 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
14571457        }
14581458      }
14591459
1460-       val  methodName  =  abstractMethod.javaSimpleName
1461-       val  applyN  =  {
1462-         val  mt  =  asmMethodType(abstractMethod)
1463-         mt.toASMType
1460+       val  methodName  =  samMethod.javaSimpleName
1461+       val  samMethodType  =  asmMethodType(samMethod).toASMType
1462+       //  scala/bug#10334: make sure that a lambda object for `T => U` has a method `apply(T)U`, not only the `(Object)Object`
1463+       //  version. Using the lambda a structural type `{def apply(t: T): U}` causes a reflective lookup for this method.
1464+       val  needsGenericBridge  =  samMethodType !=  instantiatedMethodType
1465+       val  bridgeMethods  =  atPhase(erasurePhase){
1466+         samMethod.allOverriddenSymbols.toList
14641467      }
1465-       val  bsmArgs0  =  Seq (applyN, targetHandle, constrainedType)
1466-       val  bsmArgs  = 
1467-         if  (isSerializable)
1468-           bsmArgs0 :+  Int .box(FLAG_SERIALIZABLE )
1468+       val  overriddenMethodTypes  =  bridgeMethods.map(b =>  asmMethodType(b).toASMType)
1469+ 
1470+       //  any methods which `samMethod` overrides need bridges made for them
1471+       //  this is done automatically during erasure for classes we generate, but LMF needs to have them explicitly mentioned
1472+       //  so we have to compute them at this relatively late point.
1473+       val  bridgeTypes  =  (
1474+         if  (needsGenericBridge)
1475+           instantiatedMethodType +:  overriddenMethodTypes
14691476        else 
1470-           bsmArgs0
1477+           overriddenMethodTypes
1478+       ).distinct.filterNot(_ ==  samMethodType)
1479+ 
1480+       val  needsBridges  =  bridgeTypes.nonEmpty
1481+ 
1482+       def  flagIf (b : Boolean , flag : Int ):  Int  =  if  (b) flag else  0 
1483+       val  flags  =  flagIf(isSerializable, FLAG_SERIALIZABLE ) |  flagIf(needsBridges, FLAG_BRIDGES )
1484+ 
1485+       val  bsmArgs0  =  Seq (samMethodType, targetHandle, instantiatedMethodType)
1486+       val  bsmArgs1  =  if  (flags !=  0 ) Seq (Int .box(flags)) else  Seq .empty
1487+       val  bsmArgs2  =  if  needsBridges then  bridgeTypes.length +:  bridgeTypes else  Seq .empty
1488+ 
1489+       val  bsmArgs  =  bsmArgs0 ++  bsmArgs1 ++  bsmArgs2
14711490
14721491      val  metafactory  = 
1473-         if  (isSerializable )
1474-           lambdaMetaFactoryAltMetafactoryHandle //  altMetafactory needed  to be able to pass the SERIALIZABLE flag 
1492+         if  (flags  !=   0 )
1493+           lambdaMetaFactoryAltMetafactoryHandle //  altMetafactory required  to be able to pass the flags and additional arguments if needed 
14751494        else 
14761495          lambdaMetaFactoryMetafactoryHandle
14771496
0 commit comments