@@ -109,10 +109,17 @@ class ReifyQuotes extends MacroTransformWithImplicits {
109109 def inSplice = outer != null && ! inQuote
110110
111111 /** 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.
113114 */
114115 val importedTags = new mutable.LinkedHashMap [TypeRef , Tree ]()
115116
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+
116123 /** A stack of entered symbols, to be unwound after scope exit */
117124 var enteredSyms : List [Symbol ] = Nil
118125
@@ -128,25 +135,55 @@ class ReifyQuotes extends MacroTransformWithImplicits {
128135 * defined versions. As a side effect, prepend the expressions `tag1, ..., `tagN`
129136 * as splices to `embedded`.
130137 */
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
133157 else {
134158 val itags = importedTags.toList
159+ // The tree of the tag for each tag comes from implicit search in `tryHeal`
135160 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)
144162 }
145163 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))
149185 }
186+ }
150187
151188 /** Enter staging level of symbol defined by `tree`, if applicable. */
152189 def markDef (tree : Tree )(implicit ctx : Context ) = tree match {
@@ -226,8 +263,11 @@ class ReifyQuotes extends MacroTransformWithImplicits {
226263 def checkType (pos : Position )(implicit ctx : Context ): TypeAccumulator [Unit ] = new TypeAccumulator [Unit ] {
227264 def apply (acc : Unit , tp : Type ): Unit = reporting.trace(i " check type level $tp at $level" ) {
228265 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+ }
231271 else {
232272 if (tp.isTerm) spliceOutsideQuotes(pos)
233273 tp
@@ -414,6 +454,9 @@ class ReifyQuotes extends MacroTransformWithImplicits {
414454 tree match {
415455 case Quoted (quotedTree) =>
416456 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_~ ))
417460 case tree : Select if tree.symbol.isSplice =>
418461 splice(tree)
419462 case tree : RefTree if needsLifting(tree) =>
@@ -423,7 +466,6 @@ class ReifyQuotes extends MacroTransformWithImplicits {
423466 val last = enteredSyms
424467 stats.foreach(markDef)
425468 mapOverTree(last)
426-
427469 case Inlined (call, bindings, InlineSplice (expansion @ Select (body, name))) =>
428470 // To maintain phase consistency, we move the binding of the this parameter into the spliced code
429471 val (splicedBindings, stagedBindings) = bindings.partition {
0 commit comments