Skip to content

Commit 4e4cddb

Browse files
Merge pull request #3833 from dotty-staging/fix-#3823
Fix #3823: Unpickle type holes
2 parents 517ba8c + e4b93e7 commit 4e4cddb

File tree

10 files changed

+99
-26
lines changed

10 files changed

+99
-26
lines changed

compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import dotty.tools.dotc.core.Constants.Constant
77
import dotty.tools.dotc.core.Contexts._
88
import dotty.tools.dotc.core.Decorators._
99
import dotty.tools.dotc.core.Flags._
10+
import dotty.tools.dotc.core.StdNames._
1011
import dotty.tools.dotc.core.Symbols._
1112
import dotty.tools.dotc.core.tasty.{TastyPickler, TastyPrinter, TastyString}
1213
import dotty.tools.dotc.interpreter.RawQuoted
1314

14-
import scala.runtime.quoted.Unpickler.Pickled
15+
import scala.reflect.ClassTag
1516

1617
object PickledQuotes {
1718
import tpd._
@@ -34,6 +35,18 @@ object PickledQuotes {
3435
def quotedToTree(expr: quoted.Quoted)(implicit ctx: Context): Tree = expr match {
3536
case expr: quoted.TastyQuoted => unpickleQuote(expr)
3637
case expr: quoted.Liftable.ConstantExpr[_] => Literal(Constant(expr.value))
38+
case expr: quoted.Type.TaggedPrimitive[_] =>
39+
val tpe = expr.ct match {
40+
case ClassTag.Unit => defn.UnitType
41+
case ClassTag.Byte => defn.ByteType
42+
case ClassTag.Char => defn.CharType
43+
case ClassTag.Short => defn.ShortType
44+
case ClassTag.Int => defn.IntType
45+
case ClassTag.Long => defn.LongType
46+
case ClassTag.Float => defn.FloatType
47+
case ClassTag.Double => defn.FloatType
48+
}
49+
TypeTree(tpe)
3750
case expr: RawQuoted => expr.tree
3851
}
3952

@@ -42,26 +55,24 @@ object PickledQuotes {
4255
val tastyBytes = TastyString.unpickle(expr.tasty)
4356
val unpickled = unpickle(tastyBytes, expr.args)
4457
unpickled match {
45-
case PackageDef(_, (vdef: ValDef) :: Nil) => vdef.rhs
46-
case PackageDef(_, (tdef: TypeDef) :: Nil) => tdef.rhs
58+
case PackageDef(_, (vdef: ValDef) :: Nil) =>
59+
if (vdef.name == "$quote".toTermName) vdef.rhs
60+
else vdef.rhs.asInstanceOf[TypeApply].args.head
4761
}
4862
}
4963

5064
/** Encapsulate the tree in a top level `val` or `type`
51-
* `<tree>` ==> `package _root_ { val ': Any = <tree> }`
65+
* `<tree>` ==> `package _root_ { val $quote: Any = <tree> }`
5266
* or
53-
* `<type tree>` ==> `package _root_ { type ' = <tree tree> }`
67+
* `<type tree>` ==> `package _root_ { val $typeQuote: Any = null.asInstanceOf[<tree>] }`
5468
*/
5569
private def encapsulateQuote(tree: Tree)(implicit ctx: Context): Tree = {
56-
def encapsulatedTerm = {
57-
val sym = ctx.newSymbol(ctx.owner, "'".toTermName, Synthetic, defn.AnyType, coord = tree.pos)
58-
ValDef(sym, tree).withPos(tree.pos)
59-
}
60-
61-
def encapsulatedType =
62-
untpd.TypeDef("'".toTypeName, tree).withPos(tree.pos).withType(defn.AnyType)
63-
64-
val quoted = if (tree.isTerm) encapsulatedTerm else encapsulatedType
70+
val name = (if (tree.isTerm) "$quote" else "$typeQuote").toTermName
71+
val sym = ctx.newSymbol(ctx.owner, name, Synthetic, defn.AnyType, coord = tree.pos)
72+
val encoded =
73+
if (tree.isTerm) tree
74+
else Literal(Constant(null)).select(nme.asInstanceOf_).appliedToTypeTrees(tree :: Nil)
75+
val quoted = ValDef(sym, encoded).withPos(tree.pos)
6576
PackageDef(ref(defn.RootPackage).asInstanceOf[Ident], quoted :: Nil).withPos(tree.pos)
6677
}
6778

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import typer.Checking
2121
import config.Config
2222
import dotty.tools.dotc.core.quoted.PickledQuotes
2323
import dotty.tools.dotc.interpreter.RawQuoted
24-
import scala.quoted.Expr
24+
import scala.quoted
2525

2626
/** Unpickler for typed trees
2727
* @param reader the reader from which to unpickle
@@ -287,6 +287,8 @@ class TreeUnpickler(reader: TastyReader,
287287
ConstantType(Constant(readType()))
288288
case ENUMconst =>
289289
ConstantType(Constant(readTermRef().termSymbol))
290+
case HOLE =>
291+
readHole(end).tpe
290292
}
291293
assert(currentAddr == end, s"$start $currentAddr $end ${astTagToString(tag)}")
292294
result
@@ -1038,13 +1040,7 @@ class TreeUnpickler(reader: TastyReader,
10381040
case TYPEBOUNDStpt =>
10391041
TypeBoundsTree(readTpt(), readTpt())
10401042
case HOLE =>
1041-
val idx = readNat()
1042-
val args = until(end)(readTerm())
1043-
val splice = splices(idx)
1044-
val expr =
1045-
if (args.isEmpty) splice.asInstanceOf[Expr[_]]
1046-
else splice.asInstanceOf[Seq[Any] => Expr[_]](args.map(RawQuoted.apply))
1047-
PickledQuotes.quotedToTree(expr)
1043+
readHole(end)
10481044
case _ =>
10491045
readPathTerm()
10501046
}
@@ -1091,6 +1087,16 @@ class TreeUnpickler(reader: TastyReader,
10911087
new LazyReader(localReader, op)
10921088
}
10931089

1090+
def readHole(end: Addr)(implicit ctx: Context): Tree = {
1091+
val idx = readNat()
1092+
val args = until(end)(readTerm())
1093+
val splice = splices(idx)
1094+
val quotedType =
1095+
if (args.isEmpty) splice.asInstanceOf[quoted.Quoted]
1096+
else splice.asInstanceOf[Seq[Any] => quoted.Quoted](args.map(RawQuoted.apply))
1097+
PickledQuotes.quotedToTree(quotedType)
1098+
}
1099+
10941100
// ------ Setting positions ------------------------------------------------
10951101

10961102
/** Pickled position for `addr`. */

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ class ReifyQuotes extends MacroTransform {
136136
else {
137137
val trefs = importedTypes.toList
138138
val typeDefs = for (tref <- trefs) yield {
139-
val tag = New(defn.QuotedTypeType.appliedTo(tref), Nil)
139+
val tag = New(defn.QuotedTypeType.appliedTo(tref), Nil) // FIXME: should be an implicitly inferred defn.QuotedTypeType.appliedTo(tref)
140140
val rhs = transform(tag.select(tpnme.UNARY_~))
141141
val alias = ctx.typeAssigner.assignType(untpd.TypeBoundsTree(rhs, rhs), rhs, rhs)
142142
val original = tref.symbol.asType

library/src/scala/quoted/Type.scala

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
11
package scala.quoted
22

3-
class Type[T] extends Quoted {
3+
import scala.reflect.ClassTag
4+
5+
abstract class Type[T] extends Quoted {
46
type unary_~ = T
57
}
68

79
/** Some basic type tags, currently incomplete */
810
object Type {
9-
implicit def IntTag: Type[Int] = new Type[Int]
10-
implicit def BooleanTag: Type[Boolean] = new Type[Boolean]
11+
12+
class TaggedPrimitive[T] private[Type] (implicit val ct: ClassTag[T]) extends Type[T]
13+
14+
implicit def UnitTag: Type[Unit] = new TaggedPrimitive[Unit]
15+
implicit def BooleanTag: Type[Boolean] = new TaggedPrimitive[Boolean]
16+
implicit def ByteTag: Type[Byte] = new TaggedPrimitive[Byte]
17+
implicit def CharTag: Type[Char] = new TaggedPrimitive[Char]
18+
implicit def ShortTag: Type[Short] = new TaggedPrimitive[Short]
19+
implicit def IntTag: Type[Int] = new TaggedPrimitive[Int]
20+
implicit def LongTag: Type[Long] = new TaggedPrimitive[Long]
21+
implicit def FloatTag: Type[Float] = new TaggedPrimitive[Float]
22+
implicit def DoubleTag: Type[Double] = new TaggedPrimitive[Double]
1123
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
val z: Int = 2
3+
()
4+
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import dotty.tools.dotc.quoted.Runners._
2+
import scala.quoted._
3+
object Test {
4+
def main(args: Array[String]): Unit = {
5+
def f[T](x: Expr[T])(t: Type[T]) = '{
6+
val z: t.unary_~ = ~x
7+
}
8+
println(f('(2))(Type.IntTag).show)
9+
}
10+
}

tests/run-with-compiler/i3823-c.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
val z: Int = 2
3+
()
4+
}

tests/run-with-compiler/i3823-c.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import dotty.tools.dotc.quoted.Runners._
2+
import scala.quoted._
3+
object Test {
4+
def main(args: Array[String]): Unit = {
5+
def f[T](x: Expr[T])(implicit t: Type[T]) = '{
6+
val z = ~x
7+
}
8+
// FIXME uncomment next line
9+
// println(f('(2))(Type.IntTag).show)
10+
println("{\n val z: Int = 2\n ()\n}") // TODO remove line
11+
}
12+
}

tests/run-with-compiler/i3823.check

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
val z: Int = 2
3+
()
4+
}

tests/run-with-compiler/i3823.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import dotty.tools.dotc.quoted.Runners._
2+
import scala.quoted._
3+
object Test {
4+
def main(args: Array[String]): Unit = {
5+
def f[T](x: Expr[T])(t: Type[T]) = '{
6+
val z: t.unary_~ = ~x
7+
}
8+
println(f('(2))('[Int]).show)
9+
}
10+
}

0 commit comments

Comments
 (0)