Skip to content

Remove pickled type splice type tags when unpicking #6784

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,14 @@ object PickledQuotes {
def quotedExprToTree[T](expr: quoted.Expr[T])(implicit ctx: Context): Tree = expr match {
case expr: TastyExpr[_] =>
val unpickled = unpickleExpr(expr)
val force = new TreeTraverser {
def traverse(tree: tpd.Tree)(implicit ctx: Context): Unit = traverseChildren(tree)
/** Force unpickling of the tree, removes the spliced type `@quotedTypeTag type` definitions and dealiases references to `@quotedTypeTag type` */
val forceAndCleanArtefacts = new TreeMap {
override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match {
case tree: TypeDef if tree.symbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot) => Thicket()
case tree => super.transform(tree).withType(dealiasTypeTags(tree.tpe))
}
}
force.traverse(unpickled)
unpickled
forceAndCleanArtefacts.transform(unpickled)
case expr: LiftedExpr[T] =>
expr.value match {
case value: Class[_] => ref(defn.Predef_classOf).appliedToType(classToType(value))
Expand All @@ -52,11 +55,27 @@ object PickledQuotes {

/** Transform the expression into its fully spliced TypeTree */
def quotedTypeToTree(expr: quoted.Type[_])(implicit ctx: Context): Tree = expr match {
case expr: TastyType[_] => unpickleType(expr)
case expr: TastyType[_] =>
unpickleType(expr) match {
case Block(aliases, tpt) =>
// `@quoteTypeTag type` aliasses are not required after unpickling
tpt
case tpt => tpt
}
case expr: TaggedType[_] => classTagToTypeTree(expr.ct)
case expr: TreeType[Tree] @unchecked => healOwner(expr.typeTree)
}

private def dealiasTypeTags(tp: Type)(implicit ctx: Context): Type = new TypeMap() {
override def apply(tp: Type): Type = {
val tp1 = tp match {
case tp: TypeRef if tp.typeSymbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot) => tp.dealias
case _ => tp
}
mapOver(tp1)
}
}.apply(tp)

/** Unpickle the tree contained in the TastyExpr */
private def unpickleExpr(expr: TastyExpr[_])(implicit ctx: Context): Tree = {
val tastyBytes = TastyString.unpickle(expr.tasty)
Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ class ReifyQuotes extends MacroTransform {
case tree: RefTree if !ctx.inInlineMethod =>
assert(!tree.symbol.isQuote)
assert(!tree.symbol.isSplice)
case _ : TypeDef =>
assert(!tree.symbol.hasAnnotation(defn.InternalQuoted_QuoteTypeTagAnnot),
s"${tree.symbol} should have been removed by PickledQuotes because it has a @quoteTypeTag")
case _ =>
}
}
Expand Down
11 changes: 10 additions & 1 deletion library/src-3.x/scala/internal/Quoted.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ object Quoted {
@compileTimeOnly("Illegal reference to `scala.internal.Quoted.patternBindHole`")
class patternBindHole extends Annotation

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

}
13 changes: 1 addition & 12 deletions library/src/scala/tasty/reflect/Printers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1018,7 +1018,6 @@ trait Printers
// Remove Lambda nodes, lambdas are printed by their definition
val stats2 = stats1.filter {
case Lambda(_, _) => false
case IsTypeDef(tree) => !tree.symbol.annots.exists(_.symbol.owner.fullName == "scala.internal.Quoted$.quoteTypeTag")
case _ => true
}
val (stats3, expr3) = expr1 match {
Expand Down Expand Up @@ -1515,9 +1514,6 @@ trait Printers
case Type.ConstantType(const) =>
printConstant(const)

case Type.SymRef(sym, _) if sym.annots.exists(_.symbol.owner.fullName == "scala.internal.Quoted$.quoteTypeTag") =>
printType(tpe.dealias)

case Type.SymRef(sym, prefix) if sym.isType =>
prefix match {
case Type.ThisType(Types.EmptyPackage() | Types.RootPackage()) =>
Expand Down Expand Up @@ -1575,7 +1571,7 @@ trait Printers
printRefinement(tpe)

case Type.AppliedType(tp, args) =>
normalize(tp) match {
tp match {
case Type.IsTypeLambda(tp) =>
printType(tpe.dealias)
case Type.TypeRef("<repeated>", Types.ScalaPackage()) =>
Expand Down Expand Up @@ -1674,13 +1670,6 @@ trait Printers
throw new MatchError(tpe.showExtractors)
}

private def normalize(tpe: TypeOrBounds): TypeOrBounds = tpe match {
case Type.IsSymRef(tpe)
if tpe.typeSymbol.annots.exists(_.symbol.owner.fullName == "scala.internal.Quoted$.quoteTypeTag") =>
tpe.dealias
case _ => tpe
}

def printImportSelector(sel: ImportSelector): Buffer = sel match {
case SimpleSelector(Id(name)) => this += name
case OmitSelector(Id(name)) => this += name += " => _"
Expand Down