@@ -45,6 +45,9 @@ object QuoteContextImpl {
4545
4646class QuoteContextImpl private (ctx : Context ) extends QuoteContext , QuoteUnpickler , QuoteMatching :
4747
48+ private val yCheck : Boolean =
49+ ctx.settings.Ycheck .value(using ctx).exists(x => x == " all" || x == " macros" )
50+
4851 extension [T ](self : scala.quoted.Expr [T ]):
4952 def show : String =
5053 reflect.TreeMethodsImpl .show(reflect.Term .of(self))
@@ -118,6 +121,11 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
118121 QuoteContextImpl .this .asExprOf[T ](self.asExpr)(using tp)
119122 end extension
120123
124+ extension [ThisTree <: Tree ](self : ThisTree ):
125+ def changeOwner (newOwner : Symbol ): ThisTree =
126+ tpd.TreeOps (self).changeNonLocalOwners(newOwner).asInstanceOf [ThisTree ]
127+ end extension
128+
121129 end TreeMethodsImpl
122130
123131 type PackageClause = tpd.PackageDef
@@ -238,9 +246,9 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
238246
239247 object DefDef extends DefDefModule :
240248 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 )))
242250 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 ))
244252 def unapply (ddef : DefDef ): Option [(String , List [TypeDef ], List [List [ValDef ]], TypeTree , Option [Term ])] =
245253 Some ((ddef.name.toString, ddef.typeParams, ddef.paramss, ddef.tpt, optional(ddef.rhs)))
246254 end DefDef
@@ -264,9 +272,9 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
264272
265273 object ValDef extends ValDefModule :
266274 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 ))
268276 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 ))
270278 def unapply (vdef : ValDef ): Option [(String , TypeTree , Option [Term ])] =
271279 Some ((vdef.name.toString, vdef.tpt, optional(vdef.rhs)))
272280
@@ -727,9 +735,9 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
727735 end ClosureMethodsImpl
728736
729737 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))
733741
734742 def unapply (tree : Block ): Option [(List [ValDef ], Term )] = tree match {
735743 case Block ((ddef @ DefDef (_, _, params :: Nil , _, Some (body))) :: Nil , Closure (meth, _))
@@ -2201,14 +2209,14 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
22012209 def requiredModule (path : String ): Symbol = dotc.core.Symbols .requiredModule(path)
22022210 def requiredMethod (path : String ): Symbol = dotc.core.Symbols .requiredMethod(path)
22032211 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)
22122220 def noSymbol : Symbol = dotc.core.Symbols .NoSymbol
22132221 end Symbol
22142222
@@ -2541,6 +2549,53 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
25412549 private def withDefaultPos [T <: Tree ](fn : Context ?=> T ): T =
25422550 fn(using ctx.withSource(Position .ofMacroExpansion.source)).withSpan(Position .ofMacroExpansion.span)
25432551
2552+ /** Checks that all definitions in this tree have the expected owner.
2553+ * Nested definitions are ignored and assumed to be correct by construction.
2554+ */
2555+ private def yCheckedOwners (tree : Option [Tree ], owner : Symbol ): tree.type =
2556+ if yCheck then
2557+ tree match
2558+ case Some (tree) =>
2559+ yCheckOwners(tree, owner)
2560+ case _ =>
2561+ tree
2562+
2563+ /** Checks that all definitions in this tree have the expected owner.
2564+ * Nested definitions are ignored and assumed to be correct by construction.
2565+ */
2566+ private def yCheckedOwners (tree : Tree , owner : Symbol ): tree.type =
2567+ if yCheck then
2568+ yCheckOwners(tree, owner)
2569+ tree
2570+
2571+ /** Checks that all definitions in this tree have the expected owner.
2572+ * Nested definitions are ignored and assumed to be correct by construction.
2573+ */
2574+ private def yCheckOwners (tree : Tree , owner : Symbol ): Unit =
2575+ new tpd.TreeTraverser {
2576+ def traverse (t : Tree )(using Context ): Unit =
2577+ t match
2578+ case t : tpd.DefTree =>
2579+ val defOwner = t.symbol.owner
2580+ assert(defOwner == owner,
2581+ s """ Tree had an unexpected owner for ${t.symbol}
2582+ |Expected: $owner ( ${owner.fullName})
2583+ |But was: $defOwner ( ${defOwner.fullName})
2584+ |
2585+ |
2586+ |The code of the definition of ${t.symbol} is
2587+ | ${TreeMethods .show(t)}
2588+ |
2589+ |which was found in the code
2590+ | ${TreeMethods .show(tree)}
2591+ |
2592+ |which has the AST representation
2593+ | ${TreeMethods .showExtractors(tree)}
2594+ |
2595+ | """ .stripMargin)
2596+ case _ => traverseChildren(t)
2597+ }.traverse(tree)
2598+
25442599 end reflect
25452600
25462601 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