@@ -481,6 +481,58 @@ object Erasure extends TypeTestsCasts{
481481 super .typedDefDef(ddef1, sym)
482482 }
483483
484+ /** After erasure, we may have to replace the closure method by a bridge.
485+ * LambdaMetaFactory handles this automatically for most types, but we have
486+ * to deal with boxing and unboxing of value classes ourselves.
487+ */
488+ override def typedClosure (tree : untpd.Closure , pt : Type )(implicit ctx : Context ) = {
489+ val origClosure @ Closure (_, meth, _) = super .typedClosure(tree, pt)
490+ origClosure.tpe match {
491+ case SAMType (sam) =>
492+ val implType = meth.tpe.widen
493+
494+ val List (implParamTypes) = implType.paramTypess
495+ val List (samParamTypes) = sam.info.paramTypess
496+ val implResultType = implType.resultType
497+ val samResultType = sam.info.resultType
498+
499+ // Given a value class V with an underlying type U, the following code:
500+ // val f: Function1[V, V] = x => ...
501+ // results in the creation of a closure and a method:
502+ // def $anonfun(v1: V): V = ...
503+ // val f: Function1[V, V] = closure($anonfun)
504+ // After [[Erasure]] this method will look like:
505+ // def $anonfun(v1: ErasedValueType(V, U)): ErasedValueType(V, U) = ...
506+ // And after [[ElimErasedValueType]] it will look like:
507+ // def $anonfun(v1: U): U = ...
508+ // This method does not implement the SAM of Function1[V, V] anymore and
509+ // needs to be replaced by a bridge:
510+ // def $anonfun$2(v1: V): V = new V($anonfun(v1.underlying))
511+ // val f: Function1 = closure($anonfun$2)
512+ // In general, a bridge is needed when the signature of the closure method after
513+ // Erasure contains an ErasedValueType but the corresponding type in the functional
514+ // interface is not an ErasedValueType.
515+ val bridgeNeeded =
516+ (implResultType :: implParamTypes, samResultType :: samParamTypes).zipped.forall(
517+ (implType, samType) => implType.isErasedValueType && ! samType.isErasedValueType
518+ )
519+
520+ if (bridgeNeeded) {
521+ val bridge = ctx.newSymbol(ctx.owner, nme.ANON_FUN , Flags .Synthetic | Flags .Method , sam.info)
522+ val bridgeCtx = ctx.withOwner(bridge)
523+ Closure (bridge, bridgeParamss => {
524+ implicit val ctx : Context = bridgeCtx
525+
526+ val List (bridgeParams) = bridgeParamss
527+ val rhs = Apply (meth, (bridgeParams, implParamTypes).zipped.map(adapt(_, _)))
528+ adapt(rhs, sam.info.resultType)
529+ })
530+ } else origClosure
531+ case _ =>
532+ origClosure
533+ }
534+ }
535+
484536 override def typedTypeDef (tdef : untpd.TypeDef , sym : Symbol )(implicit ctx : Context ) =
485537 EmptyTree
486538
0 commit comments