diff --git a/compiler/src/dotty/tools/dotc/ast/Trees.scala b/compiler/src/dotty/tools/dotc/ast/Trees.scala index 453516880ab9..b0c3dc3927eb 100644 --- a/compiler/src/dotty/tools/dotc/ast/Trees.scala +++ b/compiler/src/dotty/tools/dotc/ast/Trees.scala @@ -484,8 +484,10 @@ object Trees { /** { stats; expr } */ case class Block[-T >: Untyped] private[ast] (stats: List[Tree[T]], expr: Tree[T]) - extends TermTree[T] { + extends Tree[T] { type ThisTree[-T >: Untyped] = Block[T] + override def isTerm: Boolean = expr.isTerm + override def isType: Boolean = expr.isType } /** if cond then thenp else elsep */ diff --git a/compiler/src/dotty/tools/dotc/config/Printers.scala b/compiler/src/dotty/tools/dotc/config/Printers.scala index bd8cb9844c0c..8a7cd091ccb0 100644 --- a/compiler/src/dotty/tools/dotc/config/Printers.scala +++ b/compiler/src/dotty/tools/dotc/config/Printers.scala @@ -28,6 +28,7 @@ object Printers { val overload: Printer = noPrinter val patmatch: Printer = noPrinter val pickling: Printer = noPrinter + val quotePickling: Printer = noPrinter val plugins: Printer = noPrinter val simplify: Printer = noPrinter val subtyping: Printer = noPrinter diff --git a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala index bedcd8c05724..06398ff98624 100644 --- a/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala +++ b/compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala @@ -89,12 +89,12 @@ object PickledQuotes { if (tree.pos.exists) new PositionPickler(pickler, treePkl.buf.addrOfTree).picklePositions(tree :: Nil) - if (pickling ne noPrinter) + if (quotePickling ne noPrinter) println(i"**** pickling quote of \n${tree.show}") val pickled = pickler.assembleParts() - if (pickling ne noPrinter) + if (quotePickling ne noPrinter) new TastyPrinter(pickled).printContents() pickled @@ -102,7 +102,7 @@ object PickledQuotes { /** Unpickle TASTY bytes into it's tree */ private def unpickle(bytes: Array[Byte], splices: Seq[Any], isType: Boolean)(implicit ctx: Context): Tree = { - if (pickling ne noPrinter) { + if (quotePickling ne noPrinter) { println(i"**** unpickling quote from TASTY") new TastyPrinter(bytes).printContents() } @@ -112,7 +112,7 @@ object PickledQuotes { unpickler.enter(Set.empty) val tree = unpickler.tree - if (pickling ne noPrinter) + if (quotePickling ne noPrinter) println(i"**** unpickle quote ${tree.show}") tree diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 465ae5f7fbd4..f1cd996f4f18 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -4,25 +4,35 @@ package core package tasty import Comments.CommentsContext -import Contexts._, Symbols._, Types._, Scopes._, SymDenotations._, Names._, NameOps._ -import StdNames._, Flags._, Constants._, Annotations._ +import Contexts._ +import Symbols._ +import Types._ +import Scopes._ +import SymDenotations._ +import Names._ +import NameOps._ +import StdNames._ +import Flags._ +import Constants._ +import Annotations._ import NameKinds._ import typer.Checking.checkNonCyclic import util.Positions._ -import ast.{tpd, untpd, Trees} +import ast.{TreeTypeMap, Trees, tpd, untpd} import Trees._ import Decorators._ import transform.SymUtils._ import TastyBuffer._ -import scala.annotation.{tailrec, switch} + +import scala.annotation.{switch, tailrec} import scala.collection.mutable.ListBuffer import scala.collection.mutable import config.Printers.pickling import core.quoted.PickledQuotes + import scala.quoted import scala.quoted.Types.TreeType import scala.quoted.Exprs.TastyTreeExpr - import scala.annotation.internal.sharable /** Unpickler for typed trees @@ -353,8 +363,6 @@ class TreeUnpickler(reader: TastyReader, readTypeRef() match { case binder: LambdaType => binder.paramRefs(readNat()) } - case HOLE => - readHole(end, isType = true).tpe } assert(currentAddr == end, s"$start $currentAddr $end ${astTagToString(tag)}") result @@ -1166,17 +1174,32 @@ class TreeUnpickler(reader: TastyReader, setPos(start, tree) } - def readTpt()(implicit ctx: Context): Tree = - if (nextByte == SHAREDterm) { - readByte() - forkAt(readAddr()).readTpt() - } - else if (isTypeTreeTag(nextByte)) readTerm() - else { - val start = currentAddr - val tp = readType() - if (tp.exists) setPos(start, TypeTree(tp)) else EmptyTree + def readTpt()(implicit ctx: Context): Tree = { + nextByte match { + case SHAREDterm => + readByte() + forkAt(readAddr()).readTpt() + case BLOCK => + readByte() + val end = readEnd() + val typeReader = fork + skipTree() + val aliases = readStats(ctx.owner, end) + val tpt = typeReader.readTpt() + Block(aliases, tpt) + case HOLE => + readByte() + val end = readEnd() + readHole(end, isType = true) + case _ => + if (isTypeTreeTag(nextByte)) readTerm() + else { + val start = currentAddr + val tp = readType() + if (tp.exists) setPos(start, TypeTree(tp)) else EmptyTree + } } + } def readCases(end: Addr)(implicit ctx: Context): List[CaseDef] = collectWhile((nextUnsharedTag == CASEDEF) && currentAddr != end) { diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala index c39c13f97284..abbf0ec9eb2f 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TypeOrBoundsTreesOpsImpl.scala @@ -120,6 +120,13 @@ trait TypeOrBoundsTreesOpsImpl extends scala.tasty.reflect.TypeOrBoundsTreeOps w case _ => None } } + + object Block extends BlockExtractor { + def unapply(x: TypeTree)(implicit ctx: Context): Option[(List[TypeDef], TypeTree)] = x match { + case x: tpd.Block => Some((x.stats.map { case alias: TypeDef => alias }, x.expr)) + case _ => None + } + } } // ----- TypeBoundsTrees ------------------------------------------------ diff --git a/library/src-scala3/scala/StagedTuple.scala b/library/src-scala3/scala/StagedTuple.scala index 7035fd730856..c3fd0aaf45f8 100644 --- a/library/src-scala3/scala/StagedTuple.scala +++ b/library/src-scala3/scala/StagedTuple.scala @@ -208,7 +208,7 @@ object StagedTuple { that case Some(1) => if (thatSize.contains(0)) self - else stagedCons(that, self.as[Tuple1[_]], thatSize) + else stagedCons(that, '((~self).asInstanceOf[Tuple1[_]]._1), thatSize) case Some(2) => val self2 = self.as[Tuple2[_, _]] thatSize match { diff --git a/library/src-scala3/scala/Tuple.scala b/library/src-scala3/scala/Tuple.scala index ee12658d41b4..655af4d075c2 100644 --- a/library/src-scala3/scala/Tuple.scala +++ b/library/src-scala3/scala/Tuple.scala @@ -26,7 +26,7 @@ object Tuple { inline val $MaxSpecialized = 22 inline private val XXL = $MaxSpecialized + 1 - final val specialize = false + final val specialize = true type Head[+X <: NonEmptyTuple] = X match { case x *: _ => x diff --git a/library/src/scala/tasty/reflect/TypeOrBoundsTreeOps.scala b/library/src/scala/tasty/reflect/TypeOrBoundsTreeOps.scala index 45b18d22cde9..66e2feaef005 100644 --- a/library/src/scala/tasty/reflect/TypeOrBoundsTreeOps.scala +++ b/library/src/scala/tasty/reflect/TypeOrBoundsTreeOps.scala @@ -91,6 +91,11 @@ trait TypeOrBoundsTreeOps extends TastyCore { abstract class BindExtractor{ def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(String, TypeBoundsTree)] } + + val Block: BlockExtractor + abstract class BlockExtractor{ + def unapply(typeOrBoundsTree: TypeOrBoundsTree)(implicit ctx: Context): Option[(List[TypeDef], TypeTree)] + } } // ----- TypeBoundsTrees ------------------------------------------------ diff --git a/library/src/scala/tasty/util/ShowExtractors.scala b/library/src/scala/tasty/util/ShowExtractors.scala index 879666f88fa4..2e770e3d66f5 100644 --- a/library/src/scala/tasty/util/ShowExtractors.scala +++ b/library/src/scala/tasty/util/ShowExtractors.scala @@ -116,9 +116,11 @@ class ShowExtractors[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty case TypeTree.Annotated(arg, annot) => this += "TypeTree.Annotated(" += arg += ", " += annot += ")" case TypeTree.TypeLambdaTree(tparams, body) => - this += "LambdaTypeTree(" ++= tparams += ", " += body += ")" + this += "TypeTree.LambdaTypeTree(" ++= tparams += ", " += body += ")" case TypeTree.Bind(name, bounds) => - this += "Bind(" += name += ", " += bounds += ")" + this += "TypeTree.Bind(" += name += ", " += bounds += ")" + case TypeTree.Block(aliases, tpt) => + this += "TypeTree.Block(" ++= aliases += ", " += tpt += ")" case TypeBoundsTree(lo, hi) => this += "TypeBoundsTree(" += lo += ", " += hi += ")" case SyntheticBounds() => diff --git a/library/src/scala/tasty/util/ShowSourceCode.scala b/library/src/scala/tasty/util/ShowSourceCode.scala index 764b0be442bf..19b282c15eff 100644 --- a/library/src/scala/tasty/util/ShowSourceCode.scala +++ b/library/src/scala/tasty/util/ShowSourceCode.scala @@ -816,6 +816,12 @@ class ShowSourceCode[T <: Tasty with Singleton](tasty0: T) extends Show[T](tasty case TypeTree.Bind(name, _) => this += highlightTypeDef(name, color) + case TypeTree.Block(aliases, tpt) => + inBlock { + printTrees(aliases, lineBreak()) + printTypeTree(tpt) + } + case _ => throw new MatchError(tree.show) diff --git a/tests/run-with-compiler/i5247.check b/tests/run-with-compiler/i5247.check new file mode 100644 index 000000000000..16060b4698d5 --- /dev/null +++ b/tests/run-with-compiler/i5247.check @@ -0,0 +1,2 @@ +null.asInstanceOf[lang.Object] +null.asInstanceOf[scala.List[lang.Object]] diff --git a/tests/run-with-compiler/i5247.scala b/tests/run-with-compiler/i5247.scala new file mode 100644 index 000000000000..5a8d02ef3681 --- /dev/null +++ b/tests/run-with-compiler/i5247.scala @@ -0,0 +1,16 @@ +import scala.quoted._ +object Test { + def main(args: Array[String]): Unit = { + implicit val toolbox: scala.quoted.Toolbox = scala.quoted.Toolbox.make + println(foo[Object].show) + println(bar[Object].show) + } + def foo[H : Type]: Expr[H] = { + val t = '[H] + '{ null.asInstanceOf[~t] } + } + def bar[H : Type]: Expr[List[H]] = { + val t = '[List[H]] + '{ null.asInstanceOf[~t] } + } +} diff --git a/tests/run-with-compiler/quote-owners-2.check b/tests/run-with-compiler/quote-owners-2.check index 27d92e1afd31..651841382003 100644 --- a/tests/run-with-compiler/quote-owners-2.check +++ b/tests/run-with-compiler/quote-owners-2.check @@ -2,7 +2,7 @@ { def ff: scala.Int = { val a: immutable.List[scala.Int] = { - type T = immutable.List[scala.Int] + type T = scala.List[scala.Int] val b: T = scala.Nil.::[scala.Int](3) (b: collection.immutable.List[scala.Int]) }