@@ -620,25 +620,37 @@ object Erasure {
620620 // def $anonfun1(x: Object): Object = $anonfun(BoxesRunTime.unboxToInt(x))
621621 // val f: Function1 = closure($anonfun1)
622622 //
623- // In general, a bridge is needed when, after Erasure:
624- // - one of the parameter type of the closure method is a non-reference type,
625- // and the corresponding type in the SAM is a reference type
626- // - or the result type of the closure method is an erased value type
627- // and the result type in the SAM isn't
628- // However, the following exception exists: If the SAM is replaced by
629- // JFunction*mc* in [[FunctionalInterfaces]], no bridge is needed: the
630- // SAM contains default methods to handle adaptation
623+ // In general a bridge is needed when, after Erasure, one of the
624+ // parameter type or the result type of the closure method has a
625+ // different type, and we cannot rely on auto-adaptation.
626+ //
627+ // Auto-adaptation works in the following cases:
628+ // - If the SAM is replaced by JFunction*mc* in
629+ // [[FunctionalInterfaces]], no bridge is needed: the SAM contains
630+ // default methods to handle adaptation.
631+ // - If a result type of the closure method is a primitive value type
632+ // different from Unit, we can rely on the auto-adaptation done by
633+ // LMF (because it only needs to box, not unbox, so no special
634+ // handling of null is required).
635+ // - If the SAM is replaced by JProcedure* in
636+ // [[DottyBackendInterface]] (this only happens when no explicit SAM
637+ // type is given), no bridge is needed to box a Unit result type:
638+ // the SAM contains a default method to handle that.
631639 //
632640 // See test cases lambda-*.scala and t8017/ for concrete examples.
633641
634- def isReferenceType (tp : Type ) = ! tp.isPrimitiveValueType && ! tp.isErasedValueType
635-
636642 if (! defn.isSpecializableFunction(implClosure.tpe.widen.classSymbol.asClass, implParamTypes, implResultType)) {
643+ def autoAdaptedParam (tp : Type ) = ! tp.isErasedValueType && ! tp.isPrimitiveValueType
644+ val explicitSAMType = implClosure.tpt.tpe.exists
645+ def autoAdaptedResult (tp : Type ) = ! tp.isErasedValueType &&
646+ (! explicitSAMType || tp.typeSymbol != defn.UnitClass )
647+ def sameSymbol (tp1 : Type , tp2 : Type ) = tp1.typeSymbol == tp2.typeSymbol
648+
637649 val paramAdaptationNeeded =
638650 (implParamTypes, samParamTypes).zipped.exists((implType, samType) =>
639- ! isReferenceType (implType) && isReferenceType(samType ))
651+ ! sameSymbol (implType, samType ) && ! autoAdaptedParam(implType ))
640652 val resultAdaptationNeeded =
641- implResultType.isErasedValueType && ! samResultType.isErasedValueType
653+ ! sameSymbol( implResultType, samResultType) && ! autoAdaptedResult(implResultType)
642654
643655 if (paramAdaptationNeeded || resultAdaptationNeeded) {
644656 val bridgeType =
0 commit comments