@@ -109,10 +109,17 @@ class ReifyQuotes extends MacroTransformWithImplicits {
109
109
def inSplice = outer != null && ! inQuote
110
110
111
111
/** A map from type ref T to expressions of type `quoted.Type[T]`".
112
- * These will be turned into splices using `addTags`
112
+ * These will be turned into splices using `addTags` and represent type variables
113
+ * that can be possibly healed.
113
114
*/
114
115
val importedTags = new mutable.LinkedHashMap [TypeRef , Tree ]()
115
116
117
+ /** A map from type ref T to expressions of type `quoted.Type[T]`" like `importedTags`
118
+ * These will be turned into splices using `addTags` and represent types spliced
119
+ * explicitly.
120
+ */
121
+ val explicitTags = new mutable.LinkedHashSet [TypeRef ]()
122
+
116
123
/** A stack of entered symbols, to be unwound after scope exit */
117
124
var enteredSyms : List [Symbol ] = Nil
118
125
@@ -128,25 +135,55 @@ class ReifyQuotes extends MacroTransformWithImplicits {
128
135
* defined versions. As a side effect, prepend the expressions `tag1, ..., `tagN`
129
136
* as splices to `embedded`.
130
137
*/
131
- private def addTags (expr : Tree )(implicit ctx : Context ): Tree =
132
- if (importedTags.isEmpty) expr
138
+ private def addTags (expr : Tree )(implicit ctx : Context ): Tree = {
139
+
140
+ def mkTagSymbolAndAssignType (typeRef : TypeRef , tag : Tree ): Tree = {
141
+ val rhs = transform(tag.select(tpnme.UNARY_~ ))
142
+ val alias = ctx.typeAssigner.assignType(untpd.TypeBoundsTree (rhs, rhs), rhs, rhs)
143
+
144
+ val original = typeRef.symbol.asType
145
+
146
+ val local = ctx.newSymbol(
147
+ owner = ctx.owner,
148
+ name = UniqueName .fresh(" T" .toTermName).toTypeName,
149
+ flags = Synthetic ,
150
+ info = TypeAlias (tag.tpe.select(tpnme.UNARY_~ )),
151
+ coord = typeRef.prefix.termSymbol.coord).asType
152
+
153
+ ctx.typeAssigner.assignType(untpd.TypeDef (local.name, alias), local)
154
+ }
155
+
156
+ if (importedTags.isEmpty && explicitTags.isEmpty) expr
133
157
else {
134
158
val itags = importedTags.toList
159
+ // The tree of the tag for each tag comes from implicit search in `tryHeal`
135
160
val typeDefs = for ((tref, tag) <- itags) yield {
136
- val rhs = transform(tag.select(tpnme.UNARY_~ ))
137
- val alias = ctx.typeAssigner.assignType(untpd.TypeBoundsTree (rhs, rhs), rhs, rhs)
138
- val original = tref.symbol.asType
139
- val local = original.copy(
140
- owner = ctx.owner,
141
- flags = Synthetic ,
142
- info = TypeAlias (tag.tpe.select(tpnme.UNARY_~ )))
143
- ctx.typeAssigner.assignType(untpd.TypeDef (original.name, alias), local)
161
+ mkTagSymbolAndAssignType(tref, tag)
144
162
}
145
163
importedTags.clear()
146
- Block (typeDefs,
147
- new TreeTypeMap (substFrom = itags.map(_._1.symbol), substTo = typeDefs.map(_.symbol))
148
- .apply(expr))
164
+
165
+ // The tree of the tag for each tag comes from a type ref e.g., ~t
166
+ val explicitTypeDefs = for (tref <- explicitTags) yield {
167
+ val tag = ref(tref.prefix.termSymbol)
168
+ mkTagSymbolAndAssignType(tref, tag)
169
+ }
170
+ val tagsExplicitTypeDefsPairs = explicitTags.zip(explicitTypeDefs)
171
+ explicitTags.clear()
172
+
173
+ // Maps type splices to type references of tags e.g., ~t -> some type T$1
174
+ val map : Map [Type , Type ] = tagsExplicitTypeDefsPairs.map(x => (x._1, x._2.symbol.typeRef)).toMap
175
+ val tMap = new TypeMap () {
176
+ override def apply (tp : Type ): Type = map.getOrElse(tp, mapOver(tp))
177
+ }
178
+
179
+ Block (typeDefs ++ explicitTypeDefs,
180
+ new TreeTypeMap (
181
+ typeMap = tMap,
182
+ substFrom = itags.map(_._1.symbol),
183
+ substTo = typeDefs.map(_.symbol)
184
+ ).apply(expr))
149
185
}
186
+ }
150
187
151
188
/** Enter staging level of symbol defined by `tree`, if applicable. */
152
189
def markDef (tree : Tree )(implicit ctx : Context ) = tree match {
@@ -226,8 +263,11 @@ class ReifyQuotes extends MacroTransformWithImplicits {
226
263
def checkType (pos : Position )(implicit ctx : Context ): TypeAccumulator [Unit ] = new TypeAccumulator [Unit ] {
227
264
def apply (acc : Unit , tp : Type ): Unit = reporting.trace(i " check type level $tp at $level" ) {
228
265
tp match {
229
- case tp : NamedType if tp.symbol.isSplice =>
230
- if (inQuote) outer.checkType(pos).foldOver(acc, tp)
266
+ case tp : TypeRef if tp.symbol.isSplice =>
267
+ if (inQuote) {
268
+ explicitTags += tp
269
+ outer.checkType(pos).foldOver(acc, tp)
270
+ }
231
271
else {
232
272
if (tp.isTerm) spliceOutsideQuotes(pos)
233
273
tp
@@ -414,6 +454,9 @@ class ReifyQuotes extends MacroTransformWithImplicits {
414
454
tree match {
415
455
case Quoted (quotedTree) =>
416
456
quotation(quotedTree, tree)
457
+ case tree : TypeTree if tree.tpe.typeSymbol.isSplice =>
458
+ val splicedType = tree.tpe.asInstanceOf [TypeRef ].prefix.termSymbol
459
+ splice(ref(splicedType).select(tpnme.UNARY_~ ))
417
460
case tree : Select if tree.symbol.isSplice =>
418
461
splice(tree)
419
462
case tree : RefTree if needsLifting(tree) =>
@@ -423,7 +466,6 @@ class ReifyQuotes extends MacroTransformWithImplicits {
423
466
val last = enteredSyms
424
467
stats.foreach(markDef)
425
468
mapOverTree(last)
426
-
427
469
case Inlined (call, bindings, InlineSplice (expansion @ Select (body, name))) =>
428
470
// To maintain phase consistency, we move the binding of the this parameter into the spliced code
429
471
val (splicedBindings, stagedBindings) = bindings.partition {
0 commit comments