Skip to content

Commit 7c7df3b

Browse files
nicolasstuckibiboudis
authored andcommitted
Fix scala#3847: Splice type splices in TypeTrees
1 parent e5ff11c commit 7c7df3b

File tree

6 files changed

+87
-8
lines changed

6 files changed

+87
-8
lines changed

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

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ class ReifyQuotes extends MacroTransformWithImplicits {
113113
*/
114114
val importedTags = new mutable.LinkedHashMap[TypeRef, Tree]()
115115

116+
val explicitTags = new mutable.LinkedHashSet[TypeRef]()
117+
116118
/** A stack of entered symbols, to be unwound after scope exit */
117119
var enteredSyms: List[Symbol] = Nil
118120

@@ -129,7 +131,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
129131
* as splices to `embedded`.
130132
*/
131133
private def addTags(expr: Tree)(implicit ctx: Context): Tree =
132-
if (importedTags.isEmpty) expr
134+
if (importedTags.isEmpty && explicitTags.isEmpty) expr
133135
else {
134136
val itags = importedTags.toList
135137
val typeDefs = for ((tref, tag) <- itags) yield {
@@ -138,13 +140,43 @@ class ReifyQuotes extends MacroTransformWithImplicits {
138140
val original = tref.symbol.asType
139141
val local = original.copy(
140142
owner = ctx.owner,
143+
name = (original.name + "$$").toTypeName,
141144
flags = Synthetic,
142-
info = TypeAlias(tag.tpe.select(tpnme.UNARY_~)))
143-
ctx.typeAssigner.assignType(untpd.TypeDef(original.name, alias), local)
145+
info = TypeAlias(tag.tpe.select(tpnme.UNARY_~))).asType
146+
147+
ctx.typeAssigner.assignType(untpd.TypeDef(local.name, alias), local)
144148
}
145149
importedTags.clear()
146-
Block(typeDefs,
147-
new TreeTypeMap(substFrom = itags.map(_._1.symbol), substTo = typeDefs.map(_.symbol))
150+
151+
152+
val explicitTypeDefs = for (tref <- explicitTags) yield {
153+
val tag = ref(tref.prefix.termSymbol)
154+
val rhs = transform(tag.select(tpnme.UNARY_~))
155+
156+
val alias = ctx.typeAssigner.assignType(untpd.TypeBoundsTree(rhs, rhs), rhs, rhs)
157+
158+
val local = ctx.newSymbol(
159+
owner = ctx.owner,
160+
name = UniqueName.fresh("ttt".toTermName).toTypeName,
161+
flags = Synthetic,
162+
info = TypeAlias(tag.tpe.select(tpnme.UNARY_~)),
163+
coord = tref.prefix.termSymbol.coord).asType
164+
165+
(tref, ctx.typeAssigner.assignType(untpd.TypeDef(local.name, alias), local))
166+
}
167+
val map: Map[Type, Type] = explicitTypeDefs.map(x => (x._1, x._2.symbol.typeRef)).toMap
168+
val tMap = new TypeMap() {
169+
override def apply(tp: Type): Type = {
170+
if (map.contains(tp))
171+
map.apply(tp)
172+
else
173+
mapOver(tp)
174+
}
175+
}
176+
177+
Block(typeDefs ++ explicitTypeDefs.map(_._2),
178+
new TreeTypeMap(typeMap = tMap,
179+
substFrom = itags.map(_._1.symbol), substTo = typeDefs.map(_.symbol))
148180
.apply(expr))
149181
}
150182

@@ -226,8 +258,11 @@ class ReifyQuotes extends MacroTransformWithImplicits {
226258
def checkType(pos: Position)(implicit ctx: Context): TypeAccumulator[Unit] = new TypeAccumulator[Unit] {
227259
def apply(acc: Unit, tp: Type): Unit = reporting.trace(i"check type level $tp at $level") {
228260
tp match {
229-
case tp: NamedType if tp.symbol.isSplice =>
230-
if (inQuote) outer.checkType(pos).foldOver(acc, tp)
261+
case tp: TypeRef if tp.symbol.isSplice =>
262+
if (inQuote) {
263+
explicitTags += tp
264+
outer.checkType(pos).foldOver(acc, tp)
265+
}
231266
else {
232267
if (tp.isTerm) spliceOutsideQuotes(pos)
233268
tp

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: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
dotty.runtime.Arrays.newGenericArray[Int](3)(reflect.ClassTag.Int)
3+
}

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import dotty.tools.dotc.quoted.Toolbox._
2+
import scala.quoted._
3+
import scala.reflect.ClassTag
4+
5+
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)
8+
// TODO add elements
9+
}
10+
}
11+
12+
object Test {
13+
def main(args: Array[String]): Unit = {
14+
import Arrays._
15+
implicit val ct: Expr[ClassTag[Int]] = '(ClassTag.Int)
16+
val arr: Expr[Array[List[Int]]] = Array[List[Int]](List(1, 2, 3))
17+
println(arr.show)
18+
}
19+
}

tests/run-with-compiler/i3847.check

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

tests/run-with-compiler/i3847.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import dotty.tools.dotc.quoted.Toolbox._
2+
import scala.quoted._
3+
import scala.reflect.ClassTag
4+
5+
object Arrays {
6+
implicit def ArrayIsLiftable[T: Liftable](implicit t: Type[T], ct: Expr[ClassTag[T]]): Liftable[Array[T]] = (arr: Array[T]) => '{
7+
new Array[~t](~(arr.length: Expr[Int]))(~ct)
8+
// TODO add elements
9+
}
10+
}
11+
12+
object Test {
13+
def main(args: Array[String]): Unit = {
14+
import Arrays._
15+
implicit val ct: Expr[ClassTag[Int]] = '(ClassTag.Int)
16+
val arr: Expr[Array[Int]] = Array[Int](1, 2, 3)
17+
println(arr.show)
18+
}
19+
}

0 commit comments

Comments
 (0)