Skip to content

Commit 4b63dc6

Browse files
nicolasstuckibiboudis
authored andcommitted
Fix scala#3847: Splice type splices in TypeTrees
1 parent b5d0fdf commit 4b63dc6

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
@@ -112,6 +112,8 @@ class ReifyQuotes extends MacroTransformWithImplicits {
112112
*/
113113
val importedTags = new mutable.LinkedHashMap[TypeRef, Tree]()
114114

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

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

@@ -224,8 +256,11 @@ class ReifyQuotes extends MacroTransformWithImplicits {
224256
def checkType(pos: Position)(implicit ctx: Context): TypeAccumulator[Unit] = new TypeAccumulator[Unit] {
225257
def apply(acc: Unit, tp: Type): Unit = reporting.trace(i"check type level $tp at $level") {
226258
tp match {
227-
case tp: NamedType if tp.symbol.isSplice =>
228-
if (inQuote) outer.checkType(pos).foldOver(acc, tp)
259+
case tp: TypeRef if tp.symbol.isSplice =>
260+
if (inQuote) {
261+
explicitTags += tp
262+
outer.checkType(pos).foldOver(acc, tp)
263+
}
229264
else {
230265
if (tp.isTerm) spliceOutsideQuotes(pos)
231266
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)