@@ -17,13 +17,13 @@ import dotty.tools.dotc.ast.tpd
1717import dotty .tools .dotc .ast .untpd
1818import dotty .tools .dotc .config .ScalaRelease .*
1919
20- import scala .collection .mutable
2120import dotty .tools .dotc .core .Annotations ._
2221import dotty .tools .dotc .core .StdNames ._
2322import dotty .tools .dotc .quoted ._
2423import dotty .tools .dotc .inlines .Inlines
2524
2625import scala .annotation .constructorOnly
26+ import scala .collection .mutable
2727
2828/** Translates quoted terms and types to `unpickleExprV2` or `unpickleType` method calls.
2929 *
@@ -106,16 +106,19 @@ class PickleQuotes extends MacroTransform {
106106 private def extractHolesContents (quote : tpd.Quote )(using Context ): (List [Tree ], tpd.Quote ) =
107107 class HoleContentExtractor extends Transformer :
108108 private val holeContents = List .newBuilder[Tree ]
109+ private val stagedClasses = mutable.HashSet .empty[Symbol ]
109110 override def transform (tree : tpd.Tree )(using Context ): tpd.Tree =
110111 tree match
111112 case tree @ Hole (isTerm, _, _, content) =>
112113 assert(isTerm)
113114 assert(! content.isEmpty)
114115 holeContents += content
115- val holeType = getTermHoleType (tree.tpe)
116+ val holeType = getPicklableHoleType (tree.tpe, stagedClasses )
116117 val hole = untpd.cpy.Hole (tree)(content = EmptyTree ).withType(holeType)
117118 cpy.Inlined (tree)(EmptyTree , Nil , hole)
118119 case tree : DefTree =>
120+ if tree.symbol.isClass then
121+ stagedClasses += tree.symbol
119122 val newAnnotations = tree.symbol.annotations.mapconserve { annot =>
120123 annot.derivedAnnotation(transform(annot.tree)(using ctx.withOwner(tree.symbol)))
121124 }
@@ -134,19 +137,6 @@ class PickleQuotes extends MacroTransform {
134137 }
135138 }
136139
137- /** Remove references to local types that will not be defined in this quote */
138- private def getTermHoleType (using Context ) = new TypeMap () {
139- override def apply (tp : Type ): Type = tp match
140- case tp @ TypeRef (NoPrefix , _) =>
141- // reference to term with a type defined in outer quote
142- getTypeHoleType(tp)
143- case tp @ TermRef (NoPrefix , _) =>
144- // widen term refs to terms defined in outer quote
145- apply(tp.widenTermRefExpr)
146- case tp =>
147- mapOver(tp)
148- }
149-
150140 /** Get the holeContents of the transformed tree */
151141 def getContents () =
152142 val res = holeContents.result
@@ -196,11 +186,11 @@ class PickleQuotes extends MacroTransform {
196186 cpy.Quote (quote)(Block (tdefs, body1), quote.tags)
197187
198188 private def mkTagSymbolAndAssignType (typeArg : Tree , idx : Int )(using Context ): TypeDef = {
199- val holeType = getTypeHoleType (typeArg.tpe.select(tpnme.Underlying ))
189+ val holeType = getPicklableHoleType (typeArg.tpe.select(tpnme.Underlying ), _ => false )
200190 val hole = untpd.cpy.Hole (typeArg)(isTerm = false , idx, Nil , EmptyTree ).withType(holeType)
201191 val local = newSymbol(
202192 owner = ctx.owner,
203- name = UniqueName .fresh(hole.tpe.dealias.typeSymbol .name.toTypeName),
193+ name = UniqueName .fresh(typeArg.symbol .name.toTypeName),
204194 flags = Synthetic ,
205195 info = TypeAlias (typeArg.tpe.select(tpnme.Underlying )),
206196 coord = typeArg.span
@@ -209,25 +199,11 @@ class PickleQuotes extends MacroTransform {
209199 ctx.typeAssigner.assignType(untpd.TypeDef (local.name, hole), local).withSpan(typeArg.span)
210200 }
211201
212- /** Remove references to local types that will not be defined in this quote */
213- private def getTypeHoleType (using Context ) = new TypeMap () {
214- override def apply (tp : Type ): Type = tp match
215- case tp : TypeRef if tp.typeSymbol.isTypeSplice =>
216- apply(tp.dealias)
217- case tp @ TypeRef (pre, _) if isLocalPath(pre) =>
218- val hiBound = tp.typeSymbol.info match
219- case info : ClassInfo => info.parents.reduce(_ & _)
220- case info => info.hiBound
221- apply(hiBound)
222- case tp =>
223- mapOver(tp)
224-
225- private def isLocalPath (tp : Type ): Boolean = tp match
226- case NoPrefix => true
227- case tp : TermRef if ! tp.symbol.is(Package ) => isLocalPath(tp.prefix)
228- case tp => false
229- }
230-
202+ /** Avoid all non-static types except those defined in the quote. */
203+ private def getPicklableHoleType (tpe : Type , isStagedClasses : Symbol => Boolean )(using Context ) =
204+ new TypeOps .AvoidMap {
205+ def toAvoid (tp : NamedType ) = ! isStagedClasses(tp.typeSymbol) && ! isStaticPrefix(tp)
206+ }.apply(tpe)
231207}
232208
233209object PickleQuotes {
0 commit comments