Skip to content

Commit 80828c5

Browse files
committed
Contextualize owners in reflection API
* Introduce an `Owner` abstraction * Replace `Tree.changeOwner` with contextualized `Tree.adaptOwner` * Contextualize owner in `Lambda.apply` * Contextualize owner in `Term.etaExpand` * Contextualize owner in `Symbol.{newVal, newMethod, newBind}` * Recontextualize `TreeMap`, `TreeAccumulator`, `TreeTaverser` * Fix owner in `ValDef.let`
1 parent 97a6f30 commit 80828c5

File tree

23 files changed

+165
-139
lines changed

23 files changed

+165
-139
lines changed

compiler/src/scala/quoted/internal/impl/Matcher.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ object Matcher {
199199
def bodyFn(lambdaArgs: List[Tree]): Tree = {
200200
val argsMap = args.map(_.symbol).zip(lambdaArgs.asInstanceOf[List[Term]]).toMap
201201
new TreeMap {
202-
override def transformTerm(tree: Term)(using ctx: Context): Term =
202+
override def transformTerm(tree: Term)(using owner: Owner): Term =
203203
tree match
204204
case tree: Ident => summon[Env].get(tree.symbol).flatMap(argsMap.get).getOrElse(tree)
205205
case tree => super.transformTerm(tree)
@@ -211,7 +211,7 @@ object Matcher {
211211
}
212212
val argTypes = args.map(x => x.tpe.widenTermRefExpr)
213213
val resType = pattern.tpe
214-
val res = Lambda(Symbol.currentOwner, MethodType(names)(_ => argTypes, _ => resType), (meth, x) => bodyFn(x).changeOwner(meth))
214+
val res = Lambda(MethodType(names)(_ => argTypes, _ => resType), x => bodyFn(x).adaptOwner)
215215
matched(res.asExpr)
216216

217217
//
@@ -354,7 +354,7 @@ object Matcher {
354354
/** Return all free variables of the term defined in the pattern (i.e. defined in `Env`) */
355355
def freePatternVars(term: Term)(using ctx: Context, env: Env): Set[Symbol] =
356356
val accumulator = new TreeAccumulator[Set[Symbol]] {
357-
def foldTree(x: Set[Symbol], tree: Tree)(using ctx: Context): Set[Symbol] =
357+
def foldTree(x: Set[Symbol], tree: Tree)(using owner: Owner): Set[Symbol] =
358358
tree match
359359
case tree: Ident if env.contains(tree.symbol) => foldOverTree(x + tree.symbol, tree)
360360
case _ => foldOverTree(x, tree)

compiler/src/scala/quoted/internal/impl/QuoteContextImpl.scala

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
122122
end extension
123123

124124
extension [ThisTree <: Tree](self: ThisTree):
125-
def changeOwner(newOwner: Symbol): ThisTree =
125+
def adaptOwner(using newOwner: Symbol): ThisTree =
126126
tpd.TreeOps(self).changeNonLocalOwners(newOwner).asInstanceOf[ThisTree]
127127
end extension
128128

@@ -278,13 +278,14 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
278278
def unapply(vdef: ValDef): Option[(String, TypeTree, Option[Term])] =
279279
Some((vdef.name.toString, vdef.tpt, optional(vdef.rhs)))
280280

281-
def let(name: String, rhs: Term)(body: Ident => Term): Term =
282-
val vdef = tpd.SyntheticValDef(name.toTermName, rhs)
281+
def let(name: String, rhs: Term)(body: Ident => Term)(using owner: Owner): Term =
282+
val vdef = tpd.SyntheticValDef(name.toTermName, rhs)(using ctx.withOwner(owner))
283283
val ref = tpd.ref(vdef.symbol).asInstanceOf[Ident]
284284
Block(List(vdef), body(ref))
285285

286-
def let(terms: List[Term])(body: List[Ident] => Term): Term =
287-
val vdefs = terms.map(term => tpd.SyntheticValDef("x".toTermName, term))
286+
def let(terms: List[Term])(body: List[Ident] => Term)(using owner: Owner): Term =
287+
val ctx1 = ctx.withOwner(owner)
288+
val vdefs = terms.map(term => tpd.SyntheticValDef("x".toTermName, term)(using ctx1))
288289
val refs = vdefs.map(vdef => tpd.ref(vdef.symbol).asInstanceOf[Ident])
289290
Block(vdefs, body(refs))
290291
end ValDef
@@ -365,15 +366,15 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
365366
def tpe: TypeRepr = self.tpe
366367
def underlyingArgument: Term = new tpd.TreeOps(self).underlyingArgument
367368
def underlying: Term = new tpd.TreeOps(self).underlying
368-
def etaExpand(owner: Symbol): Term = self.tpe.widen match {
369+
def etaExpand(using owner: Owner): Term = self.tpe.widen match {
369370
case mtpe: Types.MethodType if !mtpe.isParamDependent =>
370371
val closureResType = mtpe.resType match {
371372
case t: Types.MethodType => t.toFunctionType()
372373
case t => t
373374
}
374375
val closureTpe = Types.MethodType(mtpe.paramNames, mtpe.paramInfos, closureResType)
375376
val closureMethod = dotc.core.Symbols.newSymbol(owner, nme.ANON_FUN, Synthetic | Method, closureTpe)
376-
tpd.Closure(closureMethod, tss => new tpd.TreeOps(self).appliedToArgs(tss.head).etaExpand(closureMethod))
377+
tpd.Closure(closureMethod, tss => new tpd.TreeOps(self).appliedToArgs(tss.head).etaExpand(using closureMethod))
377378
case _ => self
378379
}
379380

@@ -735,9 +736,9 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
735736
end ClosureMethodsImpl
736737

737738
object Lambda extends LambdaModule:
738-
def apply(owner: Symbol, tpe: MethodType, rhsFn: (Symbol, List[Tree]) => Tree): Block =
739+
def apply(tpe: MethodType, rhsFn: Owner ?=> List[Tree] => Tree)(using owner: Owner): Block =
739740
val meth = dotc.core.Symbols.newSymbol(owner, nme.ANON_FUN, Synthetic | Method, tpe)
740-
tpd.Closure(meth, tss => yCheckedOwners(rhsFn(meth, tss.head), meth))
741+
tpd.Closure(meth, tss => yCheckedOwners(rhsFn(using meth)(tss.head), meth))
741742

742743
def unapply(tree: Block): Option[(List[ValDef], Term)] = tree match {
743744
case Block((ddef @ DefDef(_, _, params :: Nil, _, Some(body))) :: Nil, Closure(meth, _))
@@ -2200,22 +2201,35 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
22002201
case _ => None
22012202
end AmbiguousImplicitsTypeTest
22022203

2204+
type Owner = dotc.core.Symbols.Symbol
2205+
2206+
object Owner extends OwnerModule:
2207+
def apply(sym: Symbol): Owner =
2208+
assert(sym.exists, "Cannot convert NoSymbol into an Owner")
2209+
sym
2210+
def spliceOwner: Owner = ctx.owner
2211+
end Owner
2212+
2213+
object OwnerMethodsImpl extends OwnerMethods:
2214+
extension (self: Owner):
2215+
def symbol: Symbol = self
2216+
end OwnerMethodsImpl
2217+
22032218
type Symbol = dotc.core.Symbols.Symbol
22042219

22052220
object Symbol extends SymbolModule:
2206-
def currentOwner(using ctx: Context): Symbol = ctx.owner
22072221
def requiredPackage(path: String): Symbol = dotc.core.Symbols.requiredPackage(path)
22082222
def requiredClass(path: String): Symbol = dotc.core.Symbols.requiredClass(path)
22092223
def requiredModule(path: String): Symbol = dotc.core.Symbols.requiredModule(path)
22102224
def requiredMethod(path: String): Symbol = dotc.core.Symbols.requiredMethod(path)
22112225
def classSymbol(fullName: String): Symbol = dotc.core.Symbols.requiredClass(fullName)
2212-
def newMethod(owner: Symbol, name: String, tpe: TypeRepr): Symbol =
2213-
newMethod(owner, name, tpe, Flags.EmptyFlags, noSymbol)
2214-
def newMethod(owner: Symbol, name: String, tpe: TypeRepr, flags: Flags, privateWithin: Symbol): Symbol =
2226+
def newMethod(name: String, tpe: TypeRepr)(using owner: Owner): Symbol =
2227+
newMethod(name, tpe, Flags.EmptyFlags, noSymbol)
2228+
def newMethod(name: String, tpe: TypeRepr, flags: Flags, privateWithin: Symbol)(using owner: Owner): Symbol =
22152229
dotc.core.Symbols.newSymbol(owner, name.toTermName, flags | dotc.core.Flags.Method, tpe, privateWithin)
2216-
def newVal(owner: Symbol, name: String, tpe: TypeRepr, flags: Flags, privateWithin: Symbol): Symbol =
2230+
def newVal(name: String, tpe: TypeRepr, flags: Flags, privateWithin: Symbol)(using owner: Owner): Symbol =
22172231
dotc.core.Symbols.newSymbol(owner, name.toTermName, flags, tpe, privateWithin)
2218-
def newBind(owner: Symbol, name: String, flags: Flags, tpe: TypeRepr): Symbol =
2232+
def newBind(name: String, flags: Flags, tpe: TypeRepr)(using owner: Owner): Symbol =
22192233
dotc.core.Symbols.newSymbol(owner, name.toTermName, flags | Case, tpe)
22202234
def noSymbol: Symbol = dotc.core.Symbols.NoSymbol
22212235
end Symbol
@@ -2593,6 +2607,7 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
25932607
|which has the AST representation
25942608
|${TreeMethods.showExtractors(tree)}
25952609
|
2610+
|Owners can be adapted using `Tree.adaptOwner`.
25962611
|""".stripMargin)
25972612
case _ => traverseChildren(t)
25982613
}.traverse(tree)

compiler/src/scala/quoted/internal/impl/printers/SourceCode.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1409,7 +1409,7 @@ object SourceCode {
14091409
private[this] val namesIndex = collection.mutable.Map.empty[String, Int]
14101410

14111411
private def splicedName(sym: Symbol): Option[String] = {
1412-
if sym.owner.isClassDef then None
1412+
if sym.maybeOwner.isClassDef then None
14131413
else names.get(sym).orElse {
14141414
val name0 = sym.name
14151415
val index = namesIndex.getOrElse(name0, 1)

library/src-bootstrapped/scala/quoted/ExprMap.scala

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ trait ExprMap:
1010
import qctx.reflect._
1111
final class MapChildren() {
1212

13-
def transformStatement(tree: Statement)(using ctx: Context): Statement = {
14-
def localCtx(definition: Definition): Context = definition.symbol.localContext
13+
def transformStatement(tree: Statement)(using owner: Owner): Statement = {
1514
tree match {
1615
case tree: Term =>
1716
transformTerm(tree, TypeRepr.of[Any])
@@ -22,15 +21,14 @@ trait ExprMap:
2221
}
2322
}
2423

25-
def transformDefinition(tree: Definition)(using ctx: Context): Definition = {
26-
def localCtx(definition: Definition): Context = definition.symbol.localContext
24+
def transformDefinition(tree: Definition)(using owner: Owner): Definition = {
2725
tree match {
2826
case tree: ValDef =>
29-
given Context = localCtx(tree)
27+
given Owner = Owner(tree.symbol)
3028
val rhs1 = tree.rhs.map(x => transformTerm(x, tree.tpt.tpe))
3129
ValDef.copy(tree)(tree.name, tree.tpt, rhs1)
3230
case tree: DefDef =>
33-
given Context = localCtx(tree)
31+
given Owner = Owner(tree.symbol)
3432
DefDef.copy(tree)(tree.name, tree.typeParams, tree.paramss, tree.returnTpt, tree.rhs.map(x => transformTerm(x, tree.returnTpt.tpe)))
3533
case tree: TypeDef =>
3634
tree
@@ -40,7 +38,7 @@ trait ExprMap:
4038
}
4139
}
4240

43-
def transformTermChildren(tree: Term, tpe: TypeRepr)(using ctx: Context): Term = tree match {
41+
def transformTermChildren(tree: Term, tpe: TypeRepr)(using owner: Owner): Term = tree match {
4442
case Ident(name) =>
4543
tree
4644
case Select(qualifier, name) =>
@@ -94,7 +92,7 @@ trait ExprMap:
9492
Inlined.copy(tree)(call, transformDefinitions(bindings), transformTerm(expansion, tpe)/*()call.symbol.localContext)*/)
9593
}
9694

97-
def transformTerm(tree: Term, tpe: TypeRepr)(using ctx: Context): Term =
95+
def transformTerm(tree: Term, tpe: TypeRepr)(using owner: Owner): Term =
9896
tree match
9997
case _: Closure =>
10098
tree
@@ -109,39 +107,39 @@ trait ExprMap:
109107
case _ =>
110108
transformTermChildren(tree, tpe)
111109

112-
def transformTypeTree(tree: TypeTree)(using ctx: Context): TypeTree = tree
110+
def transformTypeTree(tree: TypeTree)(using owner: Owner): TypeTree = tree
113111

114-
def transformCaseDef(tree: CaseDef, tpe: TypeRepr)(using ctx: Context): CaseDef =
112+
def transformCaseDef(tree: CaseDef, tpe: TypeRepr)(using owner: Owner): CaseDef =
115113
CaseDef.copy(tree)(tree.pattern, tree.guard.map(x => transformTerm(x, TypeRepr.of[Boolean])), transformTerm(tree.rhs, tpe))
116114

117-
def transformTypeCaseDef(tree: TypeCaseDef)(using ctx: Context): TypeCaseDef = {
115+
def transformTypeCaseDef(tree: TypeCaseDef)(using owner: Owner): TypeCaseDef = {
118116
TypeCaseDef.copy(tree)(transformTypeTree(tree.pattern), transformTypeTree(tree.rhs))
119117
}
120118

121-
def transformStats(trees: List[Statement])(using ctx: Context): List[Statement] =
119+
def transformStats(trees: List[Statement])(using owner: Owner): List[Statement] =
122120
trees mapConserve (transformStatement(_))
123121

124-
def transformDefinitions(trees: List[Definition])(using ctx: Context): List[Definition] =
122+
def transformDefinitions(trees: List[Definition])(using owner: Owner): List[Definition] =
125123
trees mapConserve (transformDefinition(_))
126124

127-
def transformTerms(trees: List[Term], tpes: List[TypeRepr])(using ctx: Context): List[Term] =
125+
def transformTerms(trees: List[Term], tpes: List[TypeRepr])(using owner: Owner): List[Term] =
128126
var tpes2 = tpes // TODO use proper zipConserve
129127
trees mapConserve { x =>
130128
val tpe :: tail = tpes2
131129
tpes2 = tail
132130
transformTerm(x, tpe)
133131
}
134132

135-
def transformTerms(trees: List[Term], tpe: TypeRepr)(using ctx: Context): List[Term] =
133+
def transformTerms(trees: List[Term], tpe: TypeRepr)(using owner: Owner): List[Term] =
136134
trees.mapConserve(x => transformTerm(x, tpe))
137135

138-
def transformTypeTrees(trees: List[TypeTree])(using ctx: Context): List[TypeTree] =
136+
def transformTypeTrees(trees: List[TypeTree])(using owner: Owner): List[TypeTree] =
139137
trees mapConserve (transformTypeTree(_))
140138

141-
def transformCaseDefs(trees: List[CaseDef], tpe: TypeRepr)(using ctx: Context): List[CaseDef] =
139+
def transformCaseDefs(trees: List[CaseDef], tpe: TypeRepr)(using owner: Owner): List[CaseDef] =
142140
trees mapConserve (x => transformCaseDef(x, tpe))
143141

144-
def transformTypeCaseDefs(trees: List[TypeCaseDef])(using ctx: Context): List[TypeCaseDef] =
142+
def transformTypeCaseDefs(trees: List[TypeCaseDef])(using owner: Owner): List[TypeCaseDef] =
145143
trees mapConserve (transformTypeCaseDef(_))
146144

147145
}

0 commit comments

Comments
 (0)