Skip to content

Commit 6a5da77

Browse files
committed
Remove pickled type splice type tags when unpickling
These are artefacts of pickling that should not be visible to the users in show or while pattern matching on these expressions.
1 parent e2f4070 commit 6a5da77

File tree

4 files changed

+38
-18
lines changed

4 files changed

+38
-18
lines changed

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

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,14 @@ object PickledQuotes {
3535
def quotedExprToTree[T](expr: quoted.Expr[T])(implicit ctx: Context): Tree = expr match {
3636
case expr: TastyExpr[_] =>
3737
val unpickled = unpickleExpr(expr)
38-
val force = new TreeTraverser {
39-
def traverse(tree: tpd.Tree)(implicit ctx: Context): Unit = traverseChildren(tree)
38+
/** Force unpickling of the tree, removes the spliced type `@quotedTypeTag type` definitions and dealiases references to `@quotedTypeTag type` */
39+
val forceAndCleanArtefacts = new TreeMap {
40+
override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match {
41+
case tree: TypeDef if tree.symbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot) => Thicket()
42+
case tree => super.transform(tree).withType(dealiasTypeTags(tree.tpe))
43+
}
4044
}
41-
force.traverse(unpickled)
42-
unpickled
45+
forceAndCleanArtefacts.transform(unpickled)
4346
case expr: LiftedExpr[T] =>
4447
expr.value match {
4548
case value: Class[_] => ref(defn.Predef_classOf).appliedToType(classToType(value))
@@ -52,11 +55,27 @@ object PickledQuotes {
5255

5356
/** Transform the expression into its fully spliced TypeTree */
5457
def quotedTypeToTree(expr: quoted.Type[_])(implicit ctx: Context): Tree = expr match {
55-
case expr: TastyType[_] => unpickleType(expr)
58+
case expr: TastyType[_] =>
59+
unpickleType(expr) match {
60+
case Block(aliases, tpt) =>
61+
// `@quoteTypeTag type` aliasses are not required after unpickling
62+
tpt
63+
case tpt => tpt
64+
}
5665
case expr: TaggedType[_] => classTagToTypeTree(expr.ct)
5766
case expr: TreeType[Tree] @unchecked => healOwner(expr.typeTree)
5867
}
5968

69+
private def dealiasTypeTags(tp: Type)(implicit ctx: Context): Type = new TypeMap() {
70+
override def apply(tp: Type): Type = {
71+
val tp1 = tp match {
72+
case tp: TypeRef if tp.typeSymbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot) => tp.dealias
73+
case _ => tp
74+
}
75+
mapOver(tp1)
76+
}
77+
}.apply(tp)
78+
6079
/** Unpickle the tree contained in the TastyExpr */
6180
private def unpickleExpr(expr: TastyExpr[_])(implicit ctx: Context): Tree = {
6281
val tastyBytes = TastyString.unpickle(expr.tasty)

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ class ReifyQuotes extends MacroTransform {
7676
case tree: RefTree if !ctx.inInlineMethod =>
7777
assert(!tree.symbol.isQuote)
7878
assert(!tree.symbol.isSplice)
79+
case _ : TypeDef =>
80+
assert(!tree.symbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot),
81+
s"${tree.symbol} should have been removed by PickledQuotes because it has a @quoteTypeTag")
7982
case _ =>
8083
}
8184
}

library/src-3.x/scala/internal/Quoted.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,15 @@ object Quoted {
2525
@compileTimeOnly("Illegal reference to `scala.internal.Quoted.patternBindHole`")
2626
class patternBindHole extends Annotation
2727

28-
/** Artifact of type splicing */
28+
/** Artifact of pickled type splices
29+
*
30+
* During quote reification a quote `'{ ... F[$t] ... }` will be transformed into
31+
* `'{ @quoteTypeTag type T$1 = $t ... F[T$1] ... }` to have a tree for `$t`.
32+
* This artifact is removed durring quote unpickling.
33+
*
34+
* See ReifyQuotes.scala and PickledQuotes.scala
35+
*/
36+
@compileTimeOnly("Illegal reference to `scala.internal.Quoted.patternBindHole`")
2937
class quoteTypeTag extends Annotation
38+
3039
}

library/src/scala/tasty/reflect/Printers.scala

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,6 @@ trait Printers
10181018
// Remove Lambda nodes, lambdas are printed by their definition
10191019
val stats2 = stats1.filter {
10201020
case Lambda(_, _) => false
1021-
case IsTypeDef(tree) => !tree.symbol.annots.exists(_.symbol.owner.fullName == "scala.internal.Quoted$.quoteTypeTag")
10221021
case _ => true
10231022
}
10241023
val (stats3, expr3) = expr1 match {
@@ -1515,9 +1514,6 @@ trait Printers
15151514
case Type.ConstantType(const) =>
15161515
printConstant(const)
15171516

1518-
case Type.SymRef(sym, _) if sym.annots.exists(_.symbol.owner.fullName == "scala.internal.Quoted$.quoteTypeTag") =>
1519-
printType(tpe.dealias)
1520-
15211517
case Type.SymRef(sym, prefix) if sym.isType =>
15221518
prefix match {
15231519
case Type.ThisType(Types.EmptyPackage() | Types.RootPackage()) =>
@@ -1575,7 +1571,7 @@ trait Printers
15751571
printRefinement(tpe)
15761572

15771573
case Type.AppliedType(tp, args) =>
1578-
normalize(tp) match {
1574+
tp match {
15791575
case Type.IsTypeLambda(tp) =>
15801576
printType(tpe.dealias)
15811577
case Type.TypeRef("<repeated>", Types.ScalaPackage()) =>
@@ -1674,13 +1670,6 @@ trait Printers
16741670
throw new MatchError(tpe.showExtractors)
16751671
}
16761672

1677-
private def normalize(tpe: TypeOrBounds): TypeOrBounds = tpe match {
1678-
case Type.IsSymRef(tpe)
1679-
if tpe.typeSymbol.annots.exists(_.symbol.owner.fullName == "scala.internal.Quoted$.quoteTypeTag") =>
1680-
tpe.dealias
1681-
case _ => tpe
1682-
}
1683-
16841673
def printImportSelector(sel: ImportSelector): Buffer = sel match {
16851674
case SimpleSelector(Id(name)) => this += name
16861675
case OmitSelector(Id(name)) => this += name += " => _"

0 commit comments

Comments
 (0)