Skip to content

Commit 209fdc6

Browse files
committed
Refactorings
1 parent 9ba6547 commit 209fdc6

File tree

9 files changed

+94
-160
lines changed

9 files changed

+94
-160
lines changed

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
121121
Closure(Nil, call, targetTpt))
122122
}
123123

124-
/** A closure whole anonymous function has the given method type */
124+
/** A closure whose anonymous function has the given method type */
125125
def Lambda(tpe: MethodType, rhsFn: List[Tree] => Tree)(using Context): Block = {
126-
val meth = newSymbol(ctx.owner, nme.ANON_FUN, Synthetic | Method, tpe)
126+
val meth = newAnonFun(ctx.owner, tpe)
127127
Closure(meth, tss => rhsFn(tss.head).changeOwner(ctx.owner, meth))
128128
}
129129

@@ -1108,15 +1108,14 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
11081108
def etaExpandCFT(using Context): Tree =
11091109
def expand(target: Tree, tp: Type)(using Context): Tree = tp match
11101110
case defn.ContextFunctionType(argTypes, resType, isErased) =>
1111-
val anonFun = newSymbol(
1112-
ctx.owner, nme.ANON_FUN, Flags.Synthetic | Flags.Method,
1111+
val anonFun = newAnonFun(
1112+
ctx.owner,
11131113
MethodType.companion(isContextual = true, isErased = isErased)(argTypes, resType),
11141114
coord = ctx.owner.coord)
11151115
def lambdaBody(refss: List[List[Tree]]) =
11161116
expand(target.select(nme.apply).appliedToArgss(refss), resType)(
11171117
using ctx.withOwner(anonFun))
11181118
Closure(anonFun, lambdaBody)
1119-
.showing(i"expand $tree --> $result")
11201119
case _ =>
11211120
target
11221121
expand(tree, tree.tpe.widen)

compiler/src/dotty/tools/dotc/core/Symbols.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,10 @@ object Symbols {
712712
coord: Coord = NoCoord)(using Context): TermSymbol =
713713
newSymbol(cls, nme.CONSTRUCTOR, flags | Method, MethodType(paramNames, paramTypes, cls.typeRef), privateWithin, coord)
714714

715+
/** Create an anonymous function symbol */
716+
def newAnonFun(owner: Symbol, info: Type, coord: Coord = NoCoord)(using Context): TermSymbol =
717+
newSymbol(owner, nme.ANON_FUN, Synthetic | Method, info, coord = coord)
718+
715719
/** Create an empty default constructor symbol for given class `cls`. */
716720
def newDefaultConstructor(cls: ClassSymbol)(using Context): TermSymbol =
717721
newConstructor(cls, EmptyFlags, Nil, Nil)

compiler/src/dotty/tools/dotc/transform/Bridges.scala

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ import ast.untpd
99
import collection.{mutable, immutable}
1010
import util.Spans.Span
1111
import util.SrcPos
12+
import ContextFunctionResults.{contextResultCount, contextFunctionResultTypeAfter}
13+
import StdNames.nme
14+
import Constants.Constant
15+
import TypeErasure.transformInfo
16+
import Erasure.Boxing.adaptClosure
1217

1318
/** A helper class for generating bridge methods in class `root`. */
1419
class Bridges(root: ClassSymbol, thisPhase: DenotTransformer)(using Context) {
@@ -111,13 +116,81 @@ class Bridges(root: ClassSymbol, thisPhase: DenotTransformer)(using Context) {
111116
root.delete(other)
112117
toBeRemoved += other
113118
}
119+
/** Eta expand given `tree` that has the given method type `mt`, so that
120+
* it conforms to erased result type `pt`.
121+
* To do this correctly, we have to look at the tree's original pre-erasure
122+
* type and figure out which context function types in its result are
123+
* not yet instantiated.
124+
*/
125+
def forwarder(ref: Tree, args: List[Tree], owner: Symbol, pt: Type, other: Symbol)(using Context): Tree =
126+
val origOwner = ctx.owner
127+
val member = ref.symbol
128+
val memberCount = contextResultCount(member)
129+
if memberCount == 0 then
130+
ref.appliedToTermArgs(args)
131+
else
132+
def expandArgs(args: List[Tree], owner: Symbol)(using Context): List[Tree] = args match
133+
case (bunchedParam @ Ident(nme.ALLARGS)) :: Nil =>
134+
owner.info.firstParamTypes.indices.toList.map(n =>
135+
bunchedParam
136+
.select(nme.primitive.arrayApply)
137+
.appliedTo(Literal(Constant(n)))).showing("Expand $args%, % --> $result%, %")
138+
case _ => args
139+
140+
val toAbstract: List[TermSymbol] =
141+
def anonFuns(tp: Type, n: Int, owner: Symbol): List[TermSymbol] =
142+
if n <= 0 then Nil
143+
else
144+
val defn.ContextFunctionType(argTpes, resTpe, isErased) = tp: @unchecked
145+
val anonFun = newAnonFun(
146+
owner,
147+
MethodType(if isErased then Nil else argTpes, resTpe),
148+
coord = owner.coord)
149+
anonFun :: anonFuns(resTpe, n - 1, anonFun)
150+
if memberCount == 0 then Nil
151+
else
152+
val otherCount = contextResultCount(other)
153+
val resType = contextFunctionResultTypeAfter(member, otherCount)(using preErasureCtx)
154+
anonFuns(resType, memberCount - otherCount, owner)
155+
156+
def etaExpand(args: List[Tree], anonFuns: List[TermSymbol], owner: Symbol): Tree =
157+
anonFuns match
158+
case Nil =>
159+
val app = untpd.cpy.Apply(ref)(ref, args)
160+
assert(ctx.typer.isInstanceOf[Erasure.Typer])
161+
ctx.typer.typed(app, pt)
162+
// .changeOwnerAfter(origOwner, ctx.owner, erasurePhase.asInstanceOf[Erasure])
163+
//ref.appliedToTermArgs(args)//.changeOwner(ctx.owner, owner)
164+
case anonFun :: anonFuns1 =>
165+
val origType = anonFun.info
166+
anonFun.info = transformInfo(anonFun, anonFun.info)
167+
inContext(ctx.withOwner(owner)) {
168+
def lambdaBody(refss: List[List[Tree]]) =
169+
val refs :: Nil = refss: @unchecked
170+
val expandedRefs = refs.map(_.withSpan(owner.span.endPos)) match
171+
case (bunchedParam @ Ident(nme.ALLARGS)) :: Nil =>
172+
origType.firstParamTypes.indices.toList.map(n =>
173+
bunchedParam
174+
.select(nme.primitive.arrayApply)
175+
.appliedTo(Literal(Constant(n))))
176+
case refs1 => refs1
177+
etaExpand(args ::: expandedRefs, anonFuns1, anonFun)
178+
179+
val unadapted = Closure(anonFun, lambdaBody)
180+
cpy.Block(unadapted)(unadapted.stats,
181+
adaptClosure(unadapted.expr.asInstanceOf[Closure]))
182+
}
183+
184+
//println(i"forward $ref with $args%, %, owner = $owner, $pt")
185+
etaExpand(expandArgs(args, owner)(using preErasureCtx), toAbstract, owner)
186+
//.showing(i"forward $ref with $args%, %, owner = $owner, $pt = $result")
187+
end forwarder
114188

115189
def bridgeRhs(argss: List[List[Tree]]) =
116190
assert(argss.tail.isEmpty)
117191
val ref = This(root).select(member)
118192
if member.info.isParameterless then ref // can happen if `member` is a module
119-
else if true then Erasure.Boxing.forwarder(ref, argss.head, bridge, member.info.finalResultType, other)
120-
else Erasure.partialApply(ref, argss.head)
193+
else forwarder(ref, argss.head, bridge, member.info.finalResultType, other)
121194

122195
bridges += DefDef(bridge, bridgeRhs(_).withSpan(bridge.span))
123196
}

compiler/src/dotty/tools/dotc/transform/ByNameClosures.scala

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,9 @@ class ByNameClosures extends TransformByNameApply with IdentityDenotTransformer
3030
// ExpanSAMs applied to partial functions creates methods that need
3131
// to be fully defined before converting. Test case is pos/i9391.scala.
3232

33-
override def mkByNameClosure(arg: Tree, argType: Type)(using Context): Tree = {
34-
val meth = newSymbol(
35-
ctx.owner, nme.ANON_FUN, Synthetic | Method, MethodType(Nil, Nil, argType))
33+
override def mkByNameClosure(arg: Tree, argType: Type)(using Context): Tree =
34+
val meth = newAnonFun(ctx.owner, MethodType(Nil, argType))
3635
Closure(meth, _ => arg.changeOwnerAfter(ctx.owner, meth, thisPhase)).withSpan(arg.span)
37-
}
3836
}
3937

4038
object ByNameClosures {

compiler/src/dotty/tools/dotc/transform/ContextFunctionResults.scala

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -127,25 +127,13 @@ object ContextFunctionResults:
127127
missingCR(meth.info.finalResultType, contextResultCount(meth))._1
128128
}
129129

130-
/** The rightmost context function type in the result type of `meth`
131-
* that represents `paramCount` curried, non-erased parameters that
132-
* are included in the `contextResultCount` of `meth`.
133-
* Example:
134-
*
135-
* Say we have `def m(x: A): B ?=> (C1, C2, C3) ?=> D ?=> E ?=> F`,
136-
* paramCount == 4, and the contextResultCount of `m` is 3.
137-
* Then we return the type `(C1, C2, C3) ?=> D ?=> E ?=> F`, since this
138-
* type covers the 4 rightmost parameters C1, C2, C3 and D before the
139-
* contextResultCount runs out at E ?=> F.
140-
* Erased parameters are ignored; they contribute nothing to the
141-
* parameter count.
142-
*/
143-
def contextFunctionResultTypeAfter(meth: Symbol, skipCount: Int)(using Context) =
130+
/** The `depth` levels nested context function type in the result type of `meth` */
131+
def contextFunctionResultTypeAfter(meth: Symbol, depth: Int)(using Context) =
144132
def recur(tp: Type, n: Int): Type =
145133
if n == 0 then tp
146134
else tp match
147135
case defn.ContextFunctionType(_, resTpe, _) => recur(resTpe, n - 1)
148-
recur(meth.info.finalResultType, skipCount)
136+
recur(meth.info.finalResultType, depth)
149137

150138
/** Should selection `tree` be eliminated since it refers to an `apply`
151139
* node of a context function type whose parameters will end up being

compiler/src/dotty/tools/dotc/transform/Erasure.scala

Lines changed: 2 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -386,11 +386,8 @@ object Erasure {
386386
if ahead > 0 then etaExpand(tree, ahead, pt)
387387
else*/ tree.tpe.widen match
388388
case mt: MethodType if tree.isTerm =>
389-
if mt.paramInfos.isEmpty then adaptToType(tree.appliedToNone, pt)
390-
else
391-
assert(false)
392-
etaExpand(tree, mt, pt)
393-
389+
assert(mt.paramInfos.isEmpty)
390+
adaptToType(tree.appliedToNone, pt)
394391
case tpw =>
395392
if (pt.isInstanceOf[ProtoType] || tree.tpe <:< pt)
396393
tree
@@ -539,131 +536,6 @@ object Erasure {
539536
else
540537
tree
541538
end adaptClosure
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-
613-
/** Eta expand given `tree` that has the given method type `mt`, so that
614-
* it conforms to erased result type `pt`.
615-
* To do this correctly, we have to look at the tree's original pre-erasure
616-
* type and figure out which context function types in its result are
617-
* not yet instantiated.
618-
*/
619-
def etaExpand(tree: Tree, mt: MethodType, pt: Type)(using Context): Tree =
620-
report.log(i"eta expanding $tree")
621-
val defs = new mutable.ListBuffer[Tree]
622-
val tree1 = LiftErased.liftApp(defs, tree)
623-
val xmt = if tree.isInstanceOf[Apply] then mt else expandedMethodType(mt, tree)
624-
val targetLength = xmt.paramInfos.length
625-
val origOwner = ctx.owner
626-
627-
// The original type from which closures should be constructed
628-
val origType = contextFunctionResultTypeCovering(tree.symbol, targetLength)
629-
630-
def abstracted(args: List[Tree], tp: Type, pt: Type)(using Context): Tree =
631-
if args.length < targetLength then
632-
try
633-
val defn.ContextFunctionType(argTpes, resTpe, isErased) = tp: @unchecked
634-
if isErased then abstracted(args, resTpe, pt)
635-
else
636-
val anonFun = newSymbol(
637-
ctx.owner, nme.ANON_FUN, Flags.Synthetic | Flags.Method,
638-
MethodType(argTpes, resTpe), coord = tree.span.endPos)
639-
anonFun.info = transformInfo(anonFun, anonFun.info)
640-
def lambdaBody(refss: List[List[Tree]]) =
641-
val refs :: Nil = refss: @unchecked
642-
val expandedRefs = refs.map(_.withSpan(tree.span.endPos)) match
643-
case (bunchedParam @ Ident(nme.ALLARGS)) :: Nil =>
644-
argTpes.indices.toList.map(n =>
645-
bunchedParam
646-
.select(nme.primitive.arrayApply)
647-
.appliedTo(Literal(Constant(n))))
648-
case refs1 => refs1
649-
abstracted(args ::: expandedRefs, resTpe, anonFun.info.finalResultType)(
650-
using ctx.withOwner(anonFun))
651-
652-
val unadapted = Closure(anonFun, lambdaBody)
653-
cpy.Block(unadapted)(unadapted.stats, adaptClosure(unadapted.expr.asInstanceOf[Closure]))
654-
catch case ex: MatchError =>
655-
println(i"error while abstracting tree = $tree | mt = $mt | args = $args%, % | tp = $tp | pt = $pt")
656-
throw ex
657-
else
658-
assert(args.length == targetLength, i"wrong # args tree = $tree | args = $args%, % | mt = $mt | tree type = ${tree.tpe}")
659-
val app = untpd.cpy.Apply(tree1)(tree1, args)
660-
assert(ctx.typer.isInstanceOf[Erasure.Typer])
661-
ctx.typer.typed(app, pt)
662-
.changeOwnerAfter(origOwner, ctx.owner, erasurePhase.asInstanceOf[Erasure])
663-
664-
seq(defs.toList, abstracted(Nil, origType, pt))
665-
end etaExpand
666-
667539
end Boxing
668540

669541
class Typer(erasurePhase: DenotTransformer) extends typer.ReTyper with NoChecking {

compiler/src/dotty/tools/dotc/typer/Synthesizer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class Synthesizer(typer: Typer)(using @constructorOnly c: Context):
7070
ref(defn.NoneModule))
7171
}
7272
val tpe = MethodType(List(nme.s))(_ => List(tp1), mth => defn.OptionClass.typeRef.appliedTo(mth.newParamRef(0) & tp2))
73-
val meth = newSymbol(ctx.owner, nme.ANON_FUN, Synthetic | Method, tpe, coord = span)
73+
val meth = newAnonFun(ctx.owner, tpe, coord = span)
7474
val typeTestType = defn.TypeTestClass.typeRef.appliedTo(List(tp1, tp2))
7575
Closure(meth, tss => body(tss.head).changeOwner(ctx.owner, meth), targetType = typeTestType).withSpan(span)
7676
case _ =>

compiler/src/scala/quoted/runtime/impl/QuoteMatcher.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ object QuoteMatcher {
212212
}
213213
val argTypes = args.map(x => x.tpe.widenTermRefExpr)
214214
val methTpe = MethodType(names)(_ => argTypes, _ => pattern.tpe)
215-
val meth = newSymbol(ctx.owner, nme.ANON_FUN, Synthetic | Method, methTpe)
215+
val meth = newAnonFun(ctx.owner, methTpe)
216216
def bodyFn(lambdaArgss: List[List[Tree]]): Tree = {
217217
val argsMap = args.map(_.symbol).zip(lambdaArgss.head).toMap
218218
val body = new TreeMap {

compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
385385
case t => t
386386
}
387387
val closureTpe = Types.MethodType(mtpe.paramNames, mtpe.paramInfos, closureResType)
388-
val closureMethod = dotc.core.Symbols.newSymbol(owner, nme.ANON_FUN, Synthetic | Method, closureTpe)
388+
val closureMethod = dotc.core.Symbols.newAnonFun(owner, closureTpe)
389389
tpd.Closure(closureMethod, tss => new tpd.TreeOps(self).appliedToTermArgs(tss.head).etaExpand(closureMethod))
390390
case _ => self
391391
}
@@ -793,7 +793,7 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
793793

794794
object Lambda extends LambdaModule:
795795
def apply(owner: Symbol, tpe: MethodType, rhsFn: (Symbol, List[Tree]) => Tree): Block =
796-
val meth = dotc.core.Symbols.newSymbol(owner, nme.ANON_FUN, Synthetic | Method, tpe)
796+
val meth = dotc.core.Symbols.newAnonFun(owner, tpe)
797797
tpd.Closure(meth, tss => xCheckMacroedOwners(xCheckMacroValidExpr(rhsFn(meth, tss.head.map(withDefaultPos))), meth))
798798

799799
def unapply(tree: Block): Option[(List[ValDef], Term)] = tree match {

0 commit comments

Comments
 (0)