@@ -620,25 +620,37 @@ object Erasure {
620
620
// def $anonfun1(x: Object): Object = $anonfun(BoxesRunTime.unboxToInt(x))
621
621
// val f: Function1 = closure($anonfun1)
622
622
//
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.
631
639
//
632
640
// See test cases lambda-*.scala and t8017/ for concrete examples.
633
641
634
- def isReferenceType (tp : Type ) = ! tp.isPrimitiveValueType && ! tp.isErasedValueType
635
-
636
642
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
+
637
649
val paramAdaptationNeeded =
638
650
(implParamTypes, samParamTypes).zipped.exists((implType, samType) =>
639
- ! isReferenceType (implType) && isReferenceType(samType ))
651
+ ! sameSymbol (implType, samType ) && ! autoAdaptedParam(implType ))
640
652
val resultAdaptationNeeded =
641
- implResultType.isErasedValueType && ! samResultType.isErasedValueType
653
+ ! sameSymbol( implResultType, samResultType) && ! autoAdaptedResult(implResultType)
642
654
643
655
if (paramAdaptationNeeded || resultAdaptationNeeded) {
644
656
val bridgeType =
0 commit comments