@@ -3,6 +3,7 @@ package dotc
33package transform
44
55import core .*
6+ import core .TypeErasure .erasure
67import Scopes .newScope
78import Contexts .* , Symbols .* , Types .* , Flags .* , Decorators .* , StdNames .* , Constants .*
89import MegaPhase .*
@@ -69,14 +70,52 @@ class ExpandSAMs extends MiniPhase:
6970 case _ => tp
7071 val tpe1 = collectAndStripRefinements(tpe)
7172 val Seq (samDenot) = tpe1.possibleSamMethods
72- cpy.Block (tree)(stats,
73- transformFollowingDeep :
74- AnonClass (List (tpe1),
75- List (samDenot.symbol.asTerm.name -> fn.symbol.asTerm),
76- refinements.toList,
77- adaptVarargs = true
73+ val implSym = fn.symbol.asTerm
74+
75+ // Check if SAM param erases to array but impl param doesn't (see #23179).
76+ // E.g. SAM expects Array[AnyRef] (erases to Array[Object]) but impl has
77+ // Array[? >: AnyRef] (erases to Object). In this case we need to create
78+ // a wrapper with the SAM signature that casts arguments before forwarding.
79+ val samInfo = samDenot.info
80+ val implInfo = implSym.info
81+ val needsArrayAdaptation = (samInfo, implInfo) match
82+ case (samMt : MethodType , implMt : MethodType ) =>
83+ samMt.paramInfos.lazyZip(implMt.paramInfos).exists { (samPt, implPt) =>
84+ erasure(samPt).isInstanceOf [JavaArrayType ] && ! erasure(implPt).isInstanceOf [JavaArrayType ]
85+ }
86+ case _ => false
87+
88+ val forwarderSym =
89+ if needsArrayAdaptation then
90+ // Create a wrapper method with SAM's signature that casts args to impl's types
91+ val wrapperSym = newSymbol(
92+ implSym.owner, implSym.name.asTermName, Synthetic | Method ,
93+ samInfo, coord = implSym.span).entered.asTerm
94+ val wrapperDef = DefDef (wrapperSym, paramss => {
95+ val implMt = implInfo.asInstanceOf [MethodType ]
96+ val adaptedArgs = paramss.head.lazyZip(implMt.paramInfos).map { (arg, implPt) =>
97+ if arg.tpe =:= implPt then arg else arg.cast(implPt)
98+ }
99+ ref(implSym).appliedToTermArgs(adaptedArgs)
100+ })
101+ cpy.Block (tree)(fn :: wrapperDef :: Nil ,
102+ transformFollowingDeep :
103+ AnonClass (List (tpe1),
104+ List (samDenot.symbol.asTerm.name -> wrapperSym),
105+ refinements.toList,
106+ adaptVarargs = true
107+ )
78108 )
79- )
109+ else
110+ cpy.Block (tree)(stats,
111+ transformFollowingDeep :
112+ AnonClass (List (tpe1),
113+ List (samDenot.symbol.asTerm.name -> implSym),
114+ refinements.toList,
115+ adaptVarargs = true
116+ )
117+ )
118+ forwarderSym
80119 }
81120 case _ =>
82121 tree
0 commit comments