@@ -45,6 +45,9 @@ object QuoteContextImpl {
45
45
46
46
class QuoteContextImpl private (ctx : Context ) extends QuoteContext , QuoteUnpickler , QuoteMatching :
47
47
48
+ private val yCheck : Boolean =
49
+ ctx.settings.Ycheck .value(using ctx).exists(x => x == " all" || x == " macros" )
50
+
48
51
extension [T ](self : scala.quoted.Expr [T ]):
49
52
def show : String =
50
53
reflect.TreeMethodsImpl .show(reflect.Term .of(self))
@@ -118,6 +121,11 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
118
121
QuoteContextImpl .this .asExprOf[T ](self.asExpr)(using tp)
119
122
end extension
120
123
124
+ extension [ThisTree <: Tree ](self : ThisTree ):
125
+ def changeOwner (newOwner : Symbol ): ThisTree =
126
+ tpd.TreeOps (self).changeNonLocalOwners(newOwner).asInstanceOf [ThisTree ]
127
+ end extension
128
+
121
129
end TreeMethodsImpl
122
130
123
131
type PackageClause = tpd.PackageDef
@@ -238,9 +246,9 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
238
246
239
247
object DefDef extends DefDefModule :
240
248
def apply (symbol : Symbol , rhsFn : List [TypeRepr ] => List [List [Term ]] => Option [Term ]): DefDef =
241
- withDefaultPos(tpd.polyDefDef(symbol.asTerm, tparams => vparamss => rhsFn(tparams)(vparamss).getOrElse(tpd.EmptyTree )))
249
+ withDefaultPos(tpd.polyDefDef(symbol.asTerm, tparams => vparamss => yCheckedOwners( rhsFn(tparams)(vparamss), symbol ).getOrElse(tpd.EmptyTree )))
242
250
def copy (original : Tree )(name : String , typeParams : List [TypeDef ], paramss : List [List [ValDef ]], tpt : TypeTree , rhs : Option [Term ]): DefDef =
243
- tpd.cpy.DefDef (original)(name.toTermName, typeParams, paramss, tpt, rhs.getOrElse(tpd.EmptyTree ))
251
+ tpd.cpy.DefDef (original)(name.toTermName, typeParams, paramss, tpt, yCheckedOwners( rhs, original.symbol) .getOrElse(tpd.EmptyTree ))
244
252
def unapply (ddef : DefDef ): Option [(String , List [TypeDef ], List [List [ValDef ]], TypeTree , Option [Term ])] =
245
253
Some ((ddef.name.toString, ddef.typeParams, ddef.paramss, ddef.tpt, optional(ddef.rhs)))
246
254
end DefDef
@@ -264,9 +272,9 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
264
272
265
273
object ValDef extends ValDefModule :
266
274
def apply (symbol : Symbol , rhs : Option [Term ]): ValDef =
267
- tpd.ValDef (symbol.asTerm, rhs.getOrElse(tpd.EmptyTree ))
275
+ tpd.ValDef (symbol.asTerm, yCheckedOwners( rhs, symbol) .getOrElse(tpd.EmptyTree ))
268
276
def copy (original : Tree )(name : String , tpt : TypeTree , rhs : Option [Term ]): ValDef =
269
- tpd.cpy.ValDef (original)(name.toTermName, tpt, rhs.getOrElse(tpd.EmptyTree ))
277
+ tpd.cpy.ValDef (original)(name.toTermName, tpt, yCheckedOwners( rhs, original.symbol) .getOrElse(tpd.EmptyTree ))
270
278
def unapply (vdef : ValDef ): Option [(String , TypeTree , Option [Term ])] =
271
279
Some ((vdef.name.toString, vdef.tpt, optional(vdef.rhs)))
272
280
@@ -357,15 +365,15 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
357
365
def tpe : TypeRepr = self.tpe
358
366
def underlyingArgument : Term = new tpd.TreeOps (self).underlyingArgument
359
367
def underlying : Term = new tpd.TreeOps (self).underlying
360
- def etaExpand : Term = self.tpe.widen match {
368
+ def etaExpand ( owner : Symbol ) : Term = self.tpe.widen match {
361
369
case mtpe : Types .MethodType if ! mtpe.isParamDependent =>
362
370
val closureResType = mtpe.resType match {
363
371
case t : Types .MethodType => t.toFunctionType()
364
372
case t => t
365
373
}
366
374
val closureTpe = Types .MethodType (mtpe.paramNames, mtpe.paramInfos, closureResType)
367
- val closureMethod = dotc.core.Symbols .newSymbol(ctx. owner, nme.ANON_FUN , Synthetic | Method , closureTpe)
368
- tpd.Closure (closureMethod, tss => new tpd.TreeOps (self).appliedToArgs(tss.head).etaExpand)
375
+ 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) )
369
377
case _ => self
370
378
}
371
379
@@ -727,9 +735,9 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
727
735
end ClosureMethodsImpl
728
736
729
737
object Lambda extends LambdaModule :
730
- def apply (tpe : MethodType , rhsFn : List [Tree ] => Tree ): Block =
731
- val meth = dotc.core.Symbols .newSymbol(ctx. owner, nme.ANON_FUN , Synthetic | Method , tpe)
732
- tpd.Closure (meth, tss => changeOwnerOfTree (rhsFn(tss.head), meth))
738
+ def apply (owner : Symbol , tpe : MethodType , rhsFn : ( Symbol , List [Tree ]) => Tree ): Block =
739
+ val meth = dotc.core.Symbols .newSymbol(owner, nme.ANON_FUN , Synthetic | Method , tpe)
740
+ tpd.Closure (meth, tss => yCheckedOwners (rhsFn(meth, tss.head), meth))
733
741
734
742
def unapply (tree : Block ): Option [(List [ValDef ], Term )] = tree match {
735
743
case Block ((ddef @ DefDef (_, _, params :: Nil , _, Some (body))) :: Nil , Closure (meth, _))
@@ -2201,14 +2209,14 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
2201
2209
def requiredModule (path : String ): Symbol = dotc.core.Symbols .requiredModule(path)
2202
2210
def requiredMethod (path : String ): Symbol = dotc.core.Symbols .requiredMethod(path)
2203
2211
def classSymbol (fullName : String ): Symbol = dotc.core.Symbols .requiredClass(fullName)
2204
- def newMethod (parent : Symbol , name : String , tpe : TypeRepr ): Symbol =
2205
- newMethod(parent , name, tpe, Flags .EmptyFlags , noSymbol)
2206
- def newMethod (parent : Symbol , name : String , tpe : TypeRepr , flags : Flags , privateWithin : Symbol ): Symbol =
2207
- dotc.core.Symbols .newSymbol(parent , name.toTermName, flags | dotc.core.Flags .Method , tpe, privateWithin)
2208
- def newVal (parent : Symbol , name : String , tpe : TypeRepr , flags : Flags , privateWithin : Symbol ): Symbol =
2209
- dotc.core.Symbols .newSymbol(parent , name.toTermName, flags, tpe, privateWithin)
2210
- def newBind (parent : Symbol , name : String , flags : Flags , tpe : TypeRepr ): Symbol =
2211
- dotc.core.Symbols .newSymbol(parent , name.toTermName, flags | Case , tpe)
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 =
2215
+ 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 =
2217
+ dotc.core.Symbols .newSymbol(owner , name.toTermName, flags, tpe, privateWithin)
2218
+ def newBind (owner : Symbol , name : String , flags : Flags , tpe : TypeRepr ): Symbol =
2219
+ dotc.core.Symbols .newSymbol(owner , name.toTermName, flags | Case , tpe)
2212
2220
def noSymbol : Symbol = dotc.core.Symbols .NoSymbol
2213
2221
end Symbol
2214
2222
@@ -2542,6 +2550,53 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
2542
2550
private def withDefaultPos [T <: Tree ](fn : Context ?=> T ): T =
2543
2551
fn(using ctx.withSource(Position .ofMacroExpansion.source)).withSpan(Position .ofMacroExpansion.span)
2544
2552
2553
+ /** Checks that all definitions in this tree have the expected owner.
2554
+ * Nested definitions are ignored and assumed to be correct by construction.
2555
+ */
2556
+ private def yCheckedOwners (tree : Option [Tree ], owner : Symbol ): tree.type =
2557
+ if yCheck then
2558
+ tree match
2559
+ case Some (tree) =>
2560
+ yCheckOwners(tree, owner)
2561
+ case _ =>
2562
+ tree
2563
+
2564
+ /** Checks that all definitions in this tree have the expected owner.
2565
+ * Nested definitions are ignored and assumed to be correct by construction.
2566
+ */
2567
+ private def yCheckedOwners (tree : Tree , owner : Symbol ): tree.type =
2568
+ if yCheck then
2569
+ yCheckOwners(tree, owner)
2570
+ tree
2571
+
2572
+ /** Checks that all definitions in this tree have the expected owner.
2573
+ * Nested definitions are ignored and assumed to be correct by construction.
2574
+ */
2575
+ private def yCheckOwners (tree : Tree , owner : Symbol ): Unit =
2576
+ new tpd.TreeTraverser {
2577
+ def traverse (t : Tree )(using Context ): Unit =
2578
+ t match
2579
+ case t : tpd.DefTree =>
2580
+ val defOwner = t.symbol.owner
2581
+ assert(defOwner == owner,
2582
+ s """ Tree had an unexpected owner for ${t.symbol}
2583
+ |Expected: $owner ( ${owner.fullName})
2584
+ |But was: $defOwner ( ${defOwner.fullName})
2585
+ |
2586
+ |
2587
+ |The code of the definition of ${t.symbol} is
2588
+ | ${TreeMethods .show(t)}
2589
+ |
2590
+ |which was found in the code
2591
+ | ${TreeMethods .show(tree)}
2592
+ |
2593
+ |which has the AST representation
2594
+ | ${TreeMethods .showExtractors(tree)}
2595
+ |
2596
+ | """ .stripMargin)
2597
+ case _ => traverseChildren(t)
2598
+ }.traverse(tree)
2599
+
2545
2600
end reflect
2546
2601
2547
2602
def unpickleExpr [T ](pickled : String | List [String ], typeHole : (Int , Seq [Any ]) => scala.quoted.Type [? ], termHole : (Int , Seq [Any ], scala.quoted.QuoteContext ) => scala.quoted.Expr [? ]): scala.quoted.Expr [T ] =
0 commit comments