Skip to content

Commit c8affb6

Browse files
committed
Fix #3847: handles correctly splicing of (possibly) nested parameter types
1 parent 3c1ec5a commit c8affb6

File tree

5 files changed

+47
-76
lines changed

5 files changed

+47
-76
lines changed

compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala

Lines changed: 41 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,15 @@ class ReifyQuotes extends MacroTransformWithImplicits {
109109
val embedded = new mutable.ListBuffer[Tree]
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+
*/
116121
val explicitTags = new mutable.LinkedHashSet[TypeRef]()
117122

118123
/** A stack of entered symbols, to be unwound after scope exit */
@@ -130,52 +135,43 @@ class ReifyQuotes extends MacroTransformWithImplicits {
130135
* defined versions. As a side effect, prepend the expressions `tag1, ..., `tagN`
131136
* as splices to `embedded`.
132137
*/
133-
private def addTags(expr: Tree)(implicit ctx: Context): Tree =
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+
134156
if (importedTags.isEmpty && explicitTags.isEmpty) expr
135157
else {
136158
val itags = importedTags.toList
137-
138-
println("addTags: expr: " + expr)
139-
println("addTags: tags: ")
140-
itags.foreach(println)
141-
159+
// The tree of the tag for each tag comes from implicit search in `tryHeal`
142160
val typeDefs = for ((tref, tag) <- itags) yield {
143-
val rhs = transform(tag.select(tpnme.UNARY_~))
144-
val alias = ctx.typeAssigner.assignType(untpd.TypeBoundsTree(rhs, rhs), rhs, rhs)
145-
val original = tref.symbol.asType
146-
val local = original.copy(
147-
owner = ctx.owner,
148-
name = (original.name + "$$").toTypeName,
149-
flags = Synthetic,
150-
info = TypeAlias(tag.tpe.select(tpnme.UNARY_~))).asType
151-
152-
ctx.typeAssigner.assignType(untpd.TypeDef(local.name, alias), local)
161+
mkTagSymbolAndAssignType(tref, tag)
153162
}
154163
importedTags.clear()
155164

156-
165+
// The tree of the tag for each tag comes from a type ref e.g., ~t
157166
val explicitTypeDefs = for (tref <- explicitTags) yield {
158167
val tag = ref(tref.prefix.termSymbol)
159-
val rhs = transform(tag.select(tpnme.UNARY_~))
160-
161-
val alias = ctx.typeAssigner.assignType(untpd.TypeBoundsTree(rhs, rhs), rhs, rhs)
162-
163-
val local = ctx.newSymbol(
164-
owner = ctx.owner,
165-
name = UniqueName.fresh("ttt".toTermName).toTypeName,
166-
flags = Synthetic,
167-
info = TypeAlias(tag.tpe.select(tpnme.UNARY_~)),
168-
coord = tref.prefix.termSymbol.coord).asType
169-
170-
(tref, ctx.typeAssigner.assignType(untpd.TypeDef(local.name, alias), local))
168+
mkTagSymbolAndAssignType(tref, tag)
171169
}
172-
val map: Map[Type, Type] = explicitTypeDefs.map(x => (x._1, x._2.symbol.typeRef)).toMap
173-
174-
println()
175-
println(map)
176-
println()
177-
println()
170+
val tagsExplicitTypeDefsPairs = explicitTags.zip(explicitTypeDefs)
171+
explicitTags.clear()
178172

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
179175
val tMap = new TypeMap() {
180176
override def apply(tp: Type): Type = {
181177
if (map.contains(tp))
@@ -185,16 +181,14 @@ class ReifyQuotes extends MacroTransformWithImplicits {
185181
}
186182
}
187183

188-
val ret = Block(typeDefs ++ explicitTypeDefs.map(_._2),
189-
new TreeTypeMap(typeMap = tMap,
190-
substFrom = itags.map(_._1.symbol), substTo = typeDefs.map(_.symbol))
191-
.apply(expr))
192-
193-
println("addTags: ret: " + ret)
194-
println(ret.show)
195-
println()
196-
ret
184+
Block(typeDefs ++ tagsExplicitTypeDefsPairs.map(_._2),
185+
new TreeTypeMap(
186+
typeMap = tMap,
187+
substFrom = itags.map(_._1.symbol),
188+
substTo = typeDefs.map(_.symbol)
189+
).apply(expr))
197190
}
191+
}
198192

199193
/** Enter staging level of symbol defined by `tree`, if applicable. */
200194
def markDef(tree: Tree)(implicit ctx: Context) = tree match {
@@ -230,7 +224,6 @@ class ReifyQuotes extends MacroTransformWithImplicits {
230224
* to be added to the "inconsistent phase" message.
231225
*/
232226
def tryHeal(tp: Type, pos: Position)(implicit ctx: Context): Option[String] = {
233-
// println("tryHeal: " + tp)
234227
tp match {
235228
case tp: TypeRef =>
236229
if (level == 0) {
@@ -346,13 +339,6 @@ class ReifyQuotes extends MacroTransformWithImplicits {
346339
}
347340
else {
348341
val (body1, splices) = nested(isQuote = true).split(body)
349-
350-
// println()
351-
// println("for quote: " + quote)
352-
// println("body: " + body1)
353-
// println("bodys: " + body1.show)
354-
355-
//splices.foreach(println)
356342
pickledQuote(body1, splices, isType).withPos(quote.pos)
357343
}
358344
}
@@ -395,12 +381,6 @@ class ReifyQuotes extends MacroTransformWithImplicits {
395381
}
396382
else {
397383
val (body1, quotes) = nested(isQuote = false).split(splice.qualifier)
398-
// println()
399-
// println("for splice: " + splice)
400-
// println("body: " + body1)
401-
// println("bodys: " + body1.show)
402-
//
403-
// quotes.foreach(println)
404384
makeHole(body1, quotes, splice.tpe).withPos(splice.pos)
405385
}
406386
}
@@ -501,18 +481,11 @@ class ReifyQuotes extends MacroTransformWithImplicits {
501481
case Quoted(quotedTree) =>
502482
quotation(quotedTree, tree)
503483
case tree: TypeTree if tree.tpe.typeSymbol.isSplice =>
504-
val splicedType = tree.tpe.asInstanceOf[TypeRef].prefix.termSymbol
505-
val ret = splice(ref(splicedType).select(tpnme.UNARY_~))
506-
// println()
507-
// println("TypeTree: " + tree)
508-
// println("TypeTrees: " + tree.show)
509-
// println("TypeTree ret: " + ret)
510-
// println("TypeTree rets: " + ret.show)
511-
ret
484+
val splicedType = tree.tpe.asInstanceOf[TypeRef].prefix.termSymbol
485+
splice(ref(splicedType).select(tpnme.UNARY_~))
512486
case tree: TypeApply =>
513487
super.transform(tree)
514488
case tree: Select if tree.symbol.isSplice =>
515-
// println("Select: " + tree)
516489
splice(tree)
517490
case tree: RefTree if needsLifting(tree) =>
518491
val lift = lifters(tree.symbol)

project/Build.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ object Build {
6464

6565

6666
val agentOptions = List(
67-
// "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
67+
// "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
6868
// "-agentpath:/home/dark/opt/yjp-2013-build-13072/bin/linux-x86-64/libyjpagent.so"
6969
// "-agentpath:/Applications/YourKit_Java_Profiler_2015_build_15052.app/Contents/Resources/bin/mac/libyjpagent.jnilib",
7070
// "-XX:+HeapDumpOnOutOfMemoryError", "-Xmx1g", "-Xss2m"

tests/run-with-compiler/i3847-b.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
dotty.runtime.Arrays.newGenericArray[Int](3)(reflect.ClassTag.Int)
3-
}
2+
new Array[List[Int]](1)
3+
}

tests/run-with-compiler/i3847-b.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import scala.quoted._
33
import scala.reflect.ClassTag
44

55
object Arrays {
6-
implicit def ArrayIsLiftable[T: Liftable](implicit t: Type[T], ct: Expr[ClassTag[T]]): Liftable[Array[List[T]]] = (arr: Array[List[T]]) => '{
7-
new Array[List[~t]](3)
6+
implicit def ArrayIsLiftable[T: Liftable](implicit t: Type[T]): Liftable[Array[List[T]]] = (arr: Array[List[T]]) => '{
7+
new Array[List[~t]](~(arr.length: Expr[Int]))
88
// TODO add elements
99
}
1010
}

tests/run-with-compiler/i3847.check

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
{
2-
dotty.runtime.Arrays.newGenericArray[Int](3)(reflect.ClassTag.Int)
3-
}
1+
dotty.runtime.Arrays.newGenericArray[Int](3)(reflect.ClassTag.Int)

0 commit comments

Comments
 (0)