diff --git a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala index 6610ff90b2e5..42160f6a5355 100644 --- a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala +++ b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala @@ -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)) @@ -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) diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index 37e44fc63b52..32967981b72e 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -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 _ => } } diff --git a/library/src-3.x/scala/internal/Quoted.scala b/library/src-3.x/scala/internal/Quoted.scala index b006a10ff1f5..2e940dd85794 100644 --- a/library/src-3.x/scala/internal/Quoted.scala +++ b/library/src-3.x/scala/internal/Quoted.scala @@ -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 + } diff --git a/library/src/scala/tasty/reflect/Printers.scala b/library/src/scala/tasty/reflect/Printers.scala index 2de540619ed9..29d683a23081 100644 --- a/library/src/scala/tasty/reflect/Printers.scala +++ b/library/src/scala/tasty/reflect/Printers.scala @@ -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 { @@ -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()) => @@ -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("", Types.ScalaPackage()) => @@ -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 += " => _"