Skip to content

Commit 3d51821

Browse files
committed
Fix #3823: Unpickle type holes
1 parent 6381041 commit 3d51821

File tree

4 files changed

+40
-23
lines changed

4 files changed

+40
-23
lines changed

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

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ 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-
1615
object PickledQuotes {
1716
import tpd._
1817

@@ -42,26 +41,24 @@ object PickledQuotes {
4241
val tastyBytes = TastyString.unpickle(expr.tasty)
4342
val unpickled = unpickle(tastyBytes, expr.args)
4443
unpickled match {
45-
case PackageDef(_, (vdef: ValDef) :: Nil) => vdef.rhs
46-
case PackageDef(_, (tdef: TypeDef) :: Nil) => tdef.rhs
44+
case PackageDef(_, (vdef: ValDef) :: Nil) =>
45+
if (vdef.name == "quote".toTermName) vdef.rhs
46+
else vdef.rhs.asInstanceOf[TypeApply].args.head
4747
}
4848
}
4949

5050
/** Encapsulate the tree in a top level `val` or `type`
51-
* `<tree>` ==> `package _root_ { val ': Any = <tree> }`
51+
* `<tree>` ==> `package _root_ { val quote: Any = <tree> }`
5252
* or
53-
* `<type tree>` ==> `package _root_ { type ' = <tree tree> }`
53+
* `<type tree>` ==> `package _root_ { val typeQuote: Any = null.asInstanceOf[<tree>] }`
5454
*/
5555
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
56+
val name = (if (tree.isTerm) "quote" else "typeQuote").toTermName
57+
val sym = ctx.newSymbol(ctx.owner, name, Synthetic, defn.AnyType, coord = tree.pos)
58+
val encoded =
59+
if (tree.isTerm) tree
60+
else Literal(Constant(null)).select(nme.asInstanceOf_).appliedToTypeTrees(tree :: Nil)
61+
val quoted = ValDef(sym, encoded).withPos(tree.pos)
6562
PackageDef(ref(defn.RootPackage).asInstanceOf[Ident], quoted :: Nil).withPos(tree.pos)
6663
}
6764

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
@@ -1030,13 +1032,7 @@ class TreeUnpickler(reader: TastyReader,
10301032
case TYPEBOUNDStpt =>
10311033
TypeBoundsTree(readTpt(), readTpt())
10321034
case HOLE =>
1033-
val idx = readNat()
1034-
val args = until(end)(readTerm())
1035-
val splice = splices(idx)
1036-
val expr =
1037-
if (args.isEmpty) splice.asInstanceOf[Expr[_]]
1038-
else splice.asInstanceOf[Seq[Any] => Expr[_]](args.map(RawQuoted.apply))
1039-
PickledQuotes.quotedToTree(expr)
1035+
readHole(end)
10401036
case _ =>
10411037
readPathTerm()
10421038
}
@@ -1083,6 +1079,16 @@ class TreeUnpickler(reader: TastyReader,
10831079
new LazyReader(localReader, op)
10841080
}
10851081

1082+
def readHole(end: Addr)(implicit ctx: Context): Tree = {
1083+
val idx = readNat()
1084+
val args = until(end)(readTerm())
1085+
val splice = splices(idx)
1086+
val quotedType =
1087+
if (args.isEmpty) splice.asInstanceOf[quoted.Quoted]
1088+
else splice.asInstanceOf[Seq[Any] => quoted.Quoted](args.map(RawQuoted.apply))
1089+
PickledQuotes.quotedToTree(quotedType)
1090+
}
1091+
10861092
// ------ Setting positions ------------------------------------------------
10871093

10881094
/** Pickled position for `addr`. */
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+
}
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)