@@ -247,7 +247,7 @@ object desugar {
247
247
* def f$default$2[T](x: Int) = x + "m"
248
248
*/
249
249
private def defDef (meth : DefDef , isPrimaryConstructor : Boolean = false )(using Context ): Tree =
250
- addDefaultGetters(elimContextBounds(meth, isPrimaryConstructor))
250
+ addDefaultGetters(elimContextBounds(meth, isPrimaryConstructor). asInstanceOf [ DefDef ] )
251
251
252
252
/** Drop context bounds in given TypeDef, replacing them with evidence ValDefs that
253
253
* get added to a buffer.
@@ -309,10 +309,8 @@ object desugar {
309
309
tdef1
310
310
end desugarContextBounds
311
311
312
- private def elimContextBounds (meth : DefDef , isPrimaryConstructor : Boolean )(using Context ): DefDef =
313
- val DefDef (_, paramss, tpt, rhs) = meth
312
+ def elimContextBounds (meth : Tree , isPrimaryConstructor : Boolean = false )(using Context ): Tree =
314
313
val evidenceParamBuf = mutable.ListBuffer [ValDef ]()
315
-
316
314
var seenContextBounds : Int = 0
317
315
def freshName (unused : Tree ) =
318
316
seenContextBounds += 1 // Start at 1 like FreshNameCreator.
@@ -322,7 +320,7 @@ object desugar {
322
320
// parameters of the method since shadowing does not affect
323
321
// implicit resolution in Scala 3.
324
322
325
- val paramssNoContextBounds =
323
+ def paramssNoContextBounds ( paramss : List [ ParamClause ]) : List [ ParamClause ] =
326
324
val iflag = paramss.lastOption.flatMap(_.headOption) match
327
325
case Some (param) if param.mods.isOneOf(GivenOrImplicit ) =>
328
326
param.mods.flags & GivenOrImplicit
@@ -334,16 +332,29 @@ object desugar {
334
332
tparam => desugarContextBounds(tparam, evidenceParamBuf, flags, freshName, paramss)
335
333
}(identity)
336
334
337
- rhs match
338
- case MacroTree (call) =>
339
- cpy.DefDef (meth)(rhs = call).withMods(meth.mods | Macro | Erased )
340
- case _ =>
341
- addEvidenceParams(
342
- cpy.DefDef (meth)(
343
- name = normalizeName(meth, tpt).asTermName,
344
- paramss = paramssNoContextBounds),
345
- evidenceParamBuf.toList
346
- )
335
+ meth match
336
+ case meth @ DefDef (_, paramss, tpt, rhs) =>
337
+ val newParamss = paramssNoContextBounds(paramss)
338
+ rhs match
339
+ case MacroTree (call) =>
340
+ cpy.DefDef (meth)(rhs = call).withMods(meth.mods | Macro | Erased )
341
+ case _ =>
342
+ addEvidenceParams(
343
+ cpy.DefDef (meth)(
344
+ name = normalizeName(meth, tpt).asTermName,
345
+ paramss = newParamss
346
+ ),
347
+ evidenceParamBuf.toList
348
+ )
349
+ case meth @ PolyFunction (tparams, fun) =>
350
+ val PolyFunction (tparams : List [untpd.TypeDef ] @ unchecked, fun) = meth : @ unchecked
351
+ val Function (vparams : List [untpd.ValDef ] @ unchecked, rhs) = fun : @ unchecked
352
+ val newParamss = paramssNoContextBounds(tparams :: vparams :: Nil )
353
+ val params = evidenceParamBuf.toList
354
+ val boundNames = getBoundNames(params, newParamss)
355
+ val recur = fitEvidenceParams(params, nme.apply, boundNames)
356
+ val (paramsFst, paramsSnd) = recur(newParamss)
357
+ functionsOf((paramsFst ++ paramsSnd).filter(_.nonEmpty), rhs)
347
358
end elimContextBounds
348
359
349
360
def addDefaultGetters (meth : DefDef )(using Context ): Tree =
@@ -471,6 +482,55 @@ object desugar {
471
482
case _ =>
472
483
(Nil , tree)
473
484
485
+ private def referencesName (vdef : ValDef , names : Set [TermName ])(using Context ): Boolean =
486
+ vdef.tpt.existsSubTree:
487
+ case Ident (name : TermName ) => names.contains(name)
488
+ case _ => false
489
+
490
+ /** Fit evidence `params` into the `mparamss` parameter lists */
491
+ private def fitEvidenceParams (params : List [ValDef ], methName : Name , boundNames : Set [TermName ])(mparamss : List [ParamClause ])(using Context ): (List [ParamClause ], List [ParamClause ]) = mparamss match
492
+ case ValDefs (mparams) :: _ if mparams.exists(referencesName(_, boundNames)) =>
493
+ (params :: Nil ) -> mparamss
494
+ case ValDefs (mparams @ (mparam :: _)) :: Nil if mparam.mods.isOneOf(GivenOrImplicit ) =>
495
+ val normParams =
496
+ if params.head.mods.flags.is(Given ) != mparam.mods.flags.is(Given ) then
497
+ params.map: param =>
498
+ val normFlags = param.mods.flags &~ GivenOrImplicit | (mparam.mods.flags & (GivenOrImplicit ))
499
+ param.withMods(param.mods.withFlags(normFlags))
500
+ .showing(i " adapted param $result ${result.mods.flags} for ${methName}" , Printers .desugar)
501
+ else params
502
+ ((normParams ++ mparams) :: Nil ) -> Nil
503
+ case mparams :: mparamss1 =>
504
+ val (fst, snd) = fitEvidenceParams(params, methName, boundNames)(mparamss1)
505
+ (mparams :: fst) -> snd
506
+ case Nil =>
507
+ Nil -> (params :: Nil )
508
+
509
+ /** Create a chain of possibly contextual functions from the parameter lists */
510
+ private def functionsOf (paramss : List [ParamClause ], rhs : Tree )(using Context ): Tree = paramss match
511
+ case Nil => rhs
512
+ case ValDefs (head @ (fst :: _)) :: rest if fst.mods.isOneOf(GivenOrImplicit ) =>
513
+ val paramTpts = head.map(_.tpt)
514
+ val paramNames = head.map(_.name)
515
+ val paramsErased = head.map(_.mods.flags.is(Erased ))
516
+ makeContextualFunction(paramTpts, paramNames, functionsOf(rest, rhs), paramsErased).withSpan(rhs.span)
517
+ case ValDefs (head) :: rest =>
518
+ Function (head, functionsOf(rest, rhs))
519
+ case TypeDefs (head) :: rest =>
520
+ PolyFunction (head, functionsOf(rest, rhs))
521
+ case _ =>
522
+ assert(false , i " unexpected paramss $paramss" )
523
+ EmptyTree
524
+
525
+ private def getBoundNames (params : List [ValDef ], paramss : List [ParamClause ])(using Context ): Set [TermName ] =
526
+ var boundNames = params.map(_.name).toSet // all evidence parameter + context bound proxy names
527
+ for mparams <- paramss; mparam <- mparams do
528
+ mparam match
529
+ case tparam : TypeDef if tparam.mods.annotations.exists(WitnessNamesAnnot .unapply(_).isDefined) =>
530
+ boundNames += tparam.name.toTermName
531
+ case _ =>
532
+ boundNames
533
+
474
534
/** Add all evidence parameters in `params` as implicit parameters to `meth`.
475
535
* The position of the added parameters is determined as follows:
476
536
*
@@ -485,48 +545,9 @@ object desugar {
485
545
private def addEvidenceParams (meth : DefDef , params : List [ValDef ])(using Context ): DefDef =
486
546
if params.isEmpty then return meth
487
547
488
- var boundNames = params.map(_.name).toSet // all evidence parameter + context bound proxy names
489
- for mparams <- meth.paramss; mparam <- mparams do
490
- mparam match
491
- case tparam : TypeDef if tparam.mods.annotations.exists(WitnessNamesAnnot .unapply(_).isDefined) =>
492
- boundNames += tparam.name.toTermName
493
- case _ =>
548
+ val boundNames = getBoundNames(params, meth.paramss)
494
549
495
- def referencesBoundName (vdef : ValDef ): Boolean =
496
- vdef.tpt.existsSubTree:
497
- case Ident (name : TermName ) => boundNames.contains(name)
498
- case _ => false
499
-
500
- def recur (mparamss : List [ParamClause ]): (List [ParamClause ], List [ParamClause ]) = mparamss match
501
- case ValDefs (mparams) :: _ if mparams.exists(referencesBoundName) =>
502
- (params :: Nil ) -> mparamss
503
- case ValDefs (mparams @ (mparam :: _)) :: Nil if mparam.mods.isOneOf(GivenOrImplicit ) =>
504
- val normParams =
505
- if params.head.mods.flags.is(Given ) != mparam.mods.flags.is(Given ) then
506
- params.map: param =>
507
- val normFlags = param.mods.flags &~ GivenOrImplicit | (mparam.mods.flags & (GivenOrImplicit ))
508
- param.withMods(param.mods.withFlags(normFlags))
509
- .showing(i " adapted param $result ${result.mods.flags} for ${meth.name}" , Printers .desugar)
510
- else params
511
- ((normParams ++ mparams) :: Nil ) -> Nil
512
- case mparams :: mparamss1 =>
513
- val (fst, snd) = recur(mparamss1)
514
- (mparams :: fst) -> snd
515
- case Nil =>
516
- Nil -> (params :: Nil )
517
-
518
- def functionsOf (paramss : List [ParamClause ], rhs : Tree ): Tree = paramss match
519
- case Nil => rhs
520
- case ValDefs (head @ (fst :: _)) :: rest if fst.mods.isOneOf(GivenOrImplicit ) =>
521
- val paramTpts = params.map(_.tpt)
522
- val paramNames = params.map(_.name)
523
- val paramsErased = params.map(_.mods.flags.is(Erased ))
524
- makeContextualFunction(paramTpts, paramNames, functionsOf(rest, rhs), paramsErased).withSpan(rhs.span)
525
- case ValDefs (head) :: rest =>
526
- Function (head, functionsOf(rest, rhs))
527
- case head :: _ =>
528
- assert(false , i " unexpected type parameters when adding evidence parameters to $meth" )
529
- EmptyTree
550
+ val recur = fitEvidenceParams(params, meth.name, boundNames)
530
551
531
552
if meth.hasAttachment(PolyFunctionApply ) then
532
553
meth.removeAttachment(PolyFunctionApply )
0 commit comments