Skip to content

Fix #5247: Support type blocks and fix generic tuples #5261

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 2 commits into from
Oct 20, 2018
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
4 changes: 3 additions & 1 deletion compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/config/Printers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/dotc/core/quoted/PickledQuotes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -89,20 +89,20 @@ 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
}

/** 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()
}
Expand All @@ -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
Expand Down
57 changes: 40 additions & 17 deletions compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 ------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion library/src-scala3/scala/StagedTuple.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion library/src-scala3/scala/Tuple.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions library/src/scala/tasty/reflect/TypeOrBoundsTreeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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 ------------------------------------------------
Expand Down
6 changes: 4 additions & 2 deletions library/src/scala/tasty/util/ShowExtractors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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() =>
Expand Down
6 changes: 6 additions & 0 deletions library/src/scala/tasty/util/ShowSourceCode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
2 changes: 2 additions & 0 deletions tests/run-with-compiler/i5247.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
null.asInstanceOf[lang.Object]
null.asInstanceOf[scala.List[lang.Object]]
16 changes: 16 additions & 0 deletions tests/run-with-compiler/i5247.scala
Original file line number Diff line number Diff line change
@@ -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] }
}
}
2 changes: 1 addition & 1 deletion tests/run-with-compiler/quote-owners-2.check
Original file line number Diff line number Diff line change
Expand Up @@ -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])
}
Expand Down