@@ -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,50 @@ 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
78- )
79- )
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+ if needsArrayAdaptation then
89+ // Create a wrapper method with SAM's signature that casts args to impl's types
90+ val wrapperSym = newSymbol(
91+ implSym.owner, implSym.name.asTermName, Synthetic | Method ,
92+ samInfo, coord = implSym.span).entered.asTerm
93+ val wrapperDef = DefDef (wrapperSym, paramss => {
94+ val implMt = implInfo.stripPoly.asInstanceOf [MethodType ]
95+ val adaptedArgs = paramss.head.lazyZip(implMt.paramInfos).map { (arg, implPt) =>
96+ if arg.tpe =:= implPt then arg else arg.cast(implPt)
97+ }
98+ ref(implSym).appliedToTermArgs(adaptedArgs)
99+ })
100+ cpy.Block (tree)(fn :: wrapperDef :: Nil ,
101+ transformFollowingDeep :
102+ AnonClass (List (tpe1),
103+ List (samDenot.symbol.asTerm.name -> wrapperSym),
104+ refinements.toList,
105+ adaptVarargs = true
106+ )
107+ )
108+ else
109+ cpy.Block (tree)(stats,
110+ transformFollowingDeep :
111+ AnonClass (List (tpe1),
112+ List (samDenot.symbol.asTerm.name -> implSym),
113+ refinements.toList,
114+ adaptVarargs = true
115+ )
116+ )
80117 }
81118 case _ =>
82119 tree
0 commit comments