@@ -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
@@ -357,15 +365,15 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
357365 def tpe : TypeRepr = self.tpe
358366 def underlyingArgument : Term = new tpd.TreeOps (self).underlyingArgument
359367 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 {
361369 case mtpe : Types .MethodType if ! mtpe.isParamDependent =>
362370 val closureResType = mtpe.resType match {
363371 case t : Types .MethodType => t.toFunctionType()
364372 case t => t
365373 }
366374 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) )
369377 case _ => self
370378 }
371379
@@ -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
@@ -2542,6 +2550,53 @@ class QuoteContextImpl private (ctx: Context) extends QuoteContext, QuoteUnpickl
25422550 private def withDefaultPos [T <: Tree ](fn : Context ?=> T ): T =
25432551 fn(using ctx.withSource(Position .ofMacroExpansion.source)).withSpan(Position .ofMacroExpansion.span)
25442552
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+
25452600 end reflect
25462601
25472602 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