@@ -381,26 +381,32 @@ object Erasure {
381
381
*/
382
382
def adaptToType (tree : Tree , pt : Type )(using Context ): Tree = pt match
383
383
case _ : FunProto | AnyFunctionProto => tree
384
- case _ => tree.tpe.widen match
385
- case mt : MethodType if tree.isTerm =>
386
- if mt.paramInfos.isEmpty then adaptToType(tree.appliedToNone, pt)
387
- else etaExpand(tree, mt, pt)
388
- case tpw =>
389
- if (pt.isInstanceOf [ProtoType ] || tree.tpe <:< pt)
390
- tree
391
- else if (tpw.isErasedValueType)
392
- if (pt.isErasedValueType) then
393
- tree.asInstance(pt)
384
+ case _ =>
385
+ /* val ahead = tree.attachmentOrElse(needsEta, 0)
386
+ if ahead > 0 then etaExpand(tree, ahead, pt)
387
+ else*/ tree.tpe.widen match
388
+ case mt : MethodType if tree.isTerm =>
389
+ if mt.paramInfos.isEmpty then adaptToType(tree.appliedToNone, pt)
394
390
else
391
+ assert(false )
392
+ etaExpand(tree, mt, pt)
393
+
394
+ case tpw =>
395
+ if (pt.isInstanceOf [ProtoType ] || tree.tpe <:< pt)
396
+ tree
397
+ else if (tpw.isErasedValueType)
398
+ if (pt.isErasedValueType) then
399
+ tree.asInstance(pt)
400
+ else
401
+ adaptToType(box(tree), pt)
402
+ else if (pt.isErasedValueType)
403
+ adaptToType(unbox(tree, pt), pt)
404
+ else if (tpw.isPrimitiveValueType && ! pt.isPrimitiveValueType)
395
405
adaptToType(box(tree), pt)
396
- else if (pt.isErasedValueType)
397
- adaptToType(unbox(tree, pt), pt)
398
- else if (tpw.isPrimitiveValueType && ! pt.isPrimitiveValueType)
399
- adaptToType(box(tree), pt)
400
- else if (pt.isPrimitiveValueType && ! tpw.isPrimitiveValueType)
401
- adaptToType(unbox(tree, pt), pt)
402
- else
403
- cast(tree, pt)
406
+ else if (pt.isPrimitiveValueType && ! tpw.isPrimitiveValueType)
407
+ adaptToType(unbox(tree, pt), pt)
408
+ else
409
+ cast(tree, pt)
404
410
end adaptToType
405
411
406
412
/** The following code:
@@ -534,6 +540,76 @@ object Erasure {
534
540
tree
535
541
end adaptClosure
536
542
543
+ /** Eta expand given `tree` that has the given method type `mt`, so that
544
+ * it conforms to erased result type `pt`.
545
+ * To do this correctly, we have to look at the tree's original pre-erasure
546
+ * type and figure out which context function types in its result are
547
+ * not yet instantiated.
548
+ */
549
+ def forwarder (ref : Tree , args : List [Tree ], owner : Symbol , pt : Type , other : Symbol )(using Context ): Tree =
550
+ val origOwner = ctx.owner
551
+ val member = ref.symbol
552
+ val memberCount = contextResultCount(member)
553
+ if memberCount == 0 then
554
+ ref.appliedToTermArgs(args)
555
+ else
556
+ def expandArgs (args : List [Tree ], owner : Symbol )(using Context ): List [Tree ] = args match
557
+ case (bunchedParam @ Ident (nme.ALLARGS )) :: Nil =>
558
+ owner.info.firstParamTypes.indices.toList.map(n =>
559
+ bunchedParam
560
+ .select(nme.primitive.arrayApply)
561
+ .appliedTo(Literal (Constant (n)))).showing(" Expand $args%, % --> $result%, %" )
562
+ case _ => args
563
+
564
+ val toAbstract : List [TermSymbol ] =
565
+ def anonFuns (tp : Type , n : Int , owner : Symbol ): List [TermSymbol ] =
566
+ if n <= 0 then Nil
567
+ else
568
+ val defn .ContextFunctionType (argTpes, resTpe, isErased) = tp : @ unchecked
569
+ val anonFun = newSymbol(
570
+ owner, nme.ANON_FUN , Flags .Synthetic | Flags .Method ,
571
+ MethodType (if isErased then Nil else argTpes, resTpe),
572
+ coord = owner.coord)
573
+ anonFun :: anonFuns(resTpe, n - 1 , anonFun)
574
+ if memberCount == 0 then Nil
575
+ else
576
+ val otherCount = contextResultCount(other)
577
+ val resType = contextFunctionResultTypeAfter(member, otherCount)(using preErasureCtx)
578
+ anonFuns(resType, memberCount - otherCount, owner)
579
+
580
+ def etaExpand (args : List [Tree ], anonFuns : List [TermSymbol ], owner : Symbol ): Tree =
581
+ anonFuns match
582
+ case Nil =>
583
+ val app = untpd.cpy.Apply (ref)(ref, args)
584
+ assert(ctx.typer.isInstanceOf [Erasure .Typer ])
585
+ ctx.typer.typed(app, pt)
586
+ // .changeOwnerAfter(origOwner, ctx.owner, erasurePhase.asInstanceOf[Erasure])
587
+ // ref.appliedToTermArgs(args)//.changeOwner(ctx.owner, owner)
588
+ case anonFun :: anonFuns1 =>
589
+ val origType = anonFun.info
590
+ anonFun.info = transformInfo(anonFun, anonFun.info)
591
+ inContext(ctx.withOwner(owner)) {
592
+ def lambdaBody (refss : List [List [Tree ]]) =
593
+ val refs :: Nil = refss : @ unchecked
594
+ val expandedRefs = refs.map(_.withSpan(owner.span.endPos)) match
595
+ case (bunchedParam @ Ident (nme.ALLARGS )) :: Nil =>
596
+ origType.firstParamTypes.indices.toList.map(n =>
597
+ bunchedParam
598
+ .select(nme.primitive.arrayApply)
599
+ .appliedTo(Literal (Constant (n))))
600
+ case refs1 => refs1
601
+ etaExpand(args ::: expandedRefs, anonFuns1, anonFun)
602
+
603
+ val unadapted = Closure (anonFun, lambdaBody)
604
+ cpy.Block (unadapted)(unadapted.stats,
605
+ adaptClosure(unadapted.expr.asInstanceOf [Closure ]))
606
+ }
607
+
608
+ // println(i"forward $ref with $args%, %, owner = $owner, $pt")
609
+ etaExpand(expandArgs(args, owner)(using preErasureCtx), toAbstract, owner)
610
+ // .showing(i"forward $ref with $args%, %, owner = $owner, $pt = $result")
611
+ end forwarder
612
+
537
613
/** Eta expand given `tree` that has the given method type `mt`, so that
538
614
* it conforms to erased result type `pt`.
539
615
* To do this correctly, we have to look at the tree's original pre-erasure
0 commit comments