@@ -17,13 +17,13 @@ import dotty.tools.dotc.ast.tpd
17
17
import dotty .tools .dotc .ast .untpd
18
18
import dotty .tools .dotc .config .ScalaRelease .*
19
19
20
- import scala .collection .mutable
21
20
import dotty .tools .dotc .core .Annotations ._
22
21
import dotty .tools .dotc .core .StdNames ._
23
22
import dotty .tools .dotc .quoted ._
24
23
import dotty .tools .dotc .inlines .Inlines
25
24
26
25
import scala .annotation .constructorOnly
26
+ import scala .collection .mutable
27
27
28
28
/** Translates quoted terms and types to `unpickleExprV2` or `unpickleType` method calls.
29
29
*
@@ -106,16 +106,19 @@ class PickleQuotes extends MacroTransform {
106
106
private def extractHolesContents (quote : tpd.Quote )(using Context ): (List [Tree ], tpd.Quote ) =
107
107
class HoleContentExtractor extends Transformer :
108
108
private val holeContents = List .newBuilder[Tree ]
109
+ private val stagedClasses = mutable.HashSet .empty[Symbol ]
109
110
override def transform (tree : tpd.Tree )(using Context ): tpd.Tree =
110
111
tree match
111
112
case tree @ Hole (isTerm, _, _, content) =>
112
113
assert(isTerm)
113
114
assert(! content.isEmpty)
114
115
holeContents += content
115
- val holeType = getTermHoleType (tree.tpe)
116
+ val holeType = getPicklableHoleType (tree.tpe, stagedClasses )
116
117
val hole = untpd.cpy.Hole (tree)(content = EmptyTree ).withType(holeType)
117
118
cpy.Inlined (tree)(EmptyTree , Nil , hole)
118
119
case tree : DefTree =>
120
+ if tree.symbol.isClass then
121
+ stagedClasses += tree.symbol
119
122
val newAnnotations = tree.symbol.annotations.mapconserve { annot =>
120
123
annot.derivedAnnotation(transform(annot.tree)(using ctx.withOwner(tree.symbol)))
121
124
}
@@ -134,19 +137,6 @@ class PickleQuotes extends MacroTransform {
134
137
}
135
138
}
136
139
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
-
150
140
/** Get the holeContents of the transformed tree */
151
141
def getContents () =
152
142
val res = holeContents.result
@@ -196,11 +186,11 @@ class PickleQuotes extends MacroTransform {
196
186
cpy.Quote (quote)(Block (tdefs, body1), quote.tags)
197
187
198
188
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 )
200
190
val hole = untpd.cpy.Hole (typeArg)(isTerm = false , idx, Nil , EmptyTree ).withType(holeType)
201
191
val local = newSymbol(
202
192
owner = ctx.owner,
203
- name = UniqueName .fresh(hole.tpe.dealias.typeSymbol .name.toTypeName),
193
+ name = UniqueName .fresh(typeArg.symbol .name.toTypeName),
204
194
flags = Synthetic ,
205
195
info = TypeAlias (typeArg.tpe.select(tpnme.Underlying )),
206
196
coord = typeArg.span
@@ -209,25 +199,11 @@ class PickleQuotes extends MacroTransform {
209
199
ctx.typeAssigner.assignType(untpd.TypeDef (local.name, hole), local).withSpan(typeArg.span)
210
200
}
211
201
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)
231
207
}
232
208
233
209
object PickleQuotes {
0 commit comments