aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/syntax-summary.txt4
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala10
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala8
-rw-r--r--src/dotty/tools/dotc/core/tasty/PositionPickler.scala26
-rw-r--r--src/dotty/tools/dotc/core/tasty/TastyFormat.scala142
-rw-r--r--src/dotty/tools/dotc/core/tasty/TastyPickler.scala2
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreeBuffer.scala24
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreePickler.scala387
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala114
-rw-r--r--src/dotty/tools/dotc/printing/PlainPrinter.scala7
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala55
-rw-r--r--src/dotty/tools/dotc/transform/Pickler.scala4
-rw-r--r--src/dotty/tools/dotc/transform/PostTyper.scala2
-rw-r--r--tests/pickling/annot.scala12
-rw-r--r--tests/pickling/pickleTypes.scala13
-rw-r--r--tests/pickling/simple.scala6
16 files changed, 502 insertions, 314 deletions
diff --git a/docs/syntax-summary.txt b/docs/syntax-summary.txt
index 0a52ec802..04e149de6 100644
--- a/docs/syntax-summary.txt
+++ b/docs/syntax-summary.txt
@@ -160,7 +160,7 @@ grammar.
SimpleExpr1 ::= Literal
| Path
| `_'
- | `(' ExprsInParens `)' Parens(exprs)
+ | `(' ExprsInParens2 `)' Parens(exprs)
| SimpleExpr `.' id Select(expr, id)
| SimpleExpr (TypeArgs | NamedTypeArgs) TypeApply(expr, args)
| SimpleExpr1 ArgumentExprs Apply(expr, args)
@@ -210,7 +210,7 @@ grammar.
| SimplePattern1 `.' id
PatVar ::= varid
| `_'
- Patterns ::= Pattern [`,' Pattern]
+ Patterns ::= Pattern {`,' Pattern}
ArgumentPatterns ::= `(' [Patterns] `)' Apply(fn, pats)
| `(' [Patterns `,'] Pattern2 `:' `_' `*' ')
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index db2ce5649..09f2099d2 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -133,7 +133,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def OrTypeTree(left: Tree, right: Tree)(implicit ctx: Context): OrTypeTree =
ta.assignType(untpd.OrTypeTree(left, right), left, right)
- // RefinedTypeTree is missing, handled specially in Typer and Unpickler.
+ def RefinedTypeTree(parent: Tree, refinements: List[Tree], refineCls: ClassSymbol)(implicit ctx: Context): Tree =
+ ta.assignType(untpd.RefinedTypeTree(parent, refinements), parent, refinements, refineCls)
def AppliedTypeTree(tycon: Tree, args: List[Tree])(implicit ctx: Context): AppliedTypeTree =
ta.assignType(untpd.AppliedTypeTree(tycon, args), tycon, args)
@@ -141,6 +142,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def ByNameTypeTree(result: Tree)(implicit ctx: Context): ByNameTypeTree =
ta.assignType(untpd.ByNameTypeTree(result), result)
+ def PolyTypeTree(tparams: List[TypeDef], body: Tree)(implicit ctx: Context): PolyTypeTree =
+ ta.assignType(untpd.PolyTypeTree(tparams, body), tparams, body)
+
def TypeBoundsTree(lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree =
ta.assignType(untpd.TypeBoundsTree(lo, hi), lo, hi)
@@ -306,8 +310,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
case _ =>
false
}
- typeIsElidable ||
- tp.symbol.is(JavaStatic) ||
+ typeIsElidable ||
+ tp.symbol.is(JavaStatic) ||
tp.symbol.hasAnnotation(defn.ScalaStaticAnnot)
}
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index 62fa2d07d..7b51a58d1 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -633,9 +633,9 @@ class Definitions {
name.startsWith(prefix) && name.drop(prefix.length).forall(_.isDigit)
}
- def isBottomClass(cls: Symbol) =
+ def isBottomClass(cls: Symbol) =
cls == NothingClass || cls == NullClass
- def isBottomType(tp: Type) =
+ def isBottomType(tp: Type) =
tp.derivesFrom(NothingClass) || tp.derivesFrom(NullClass)
def isFunctionClass(cls: Symbol) = isVarArityClass(cls, tpnme.Function)
@@ -785,8 +785,8 @@ class Definitions {
if (!_isInitialized) {
// force initialization of every symbol that is synthesized or hijacked by the compiler
val forced = syntheticCoreClasses ++ syntheticCoreMethods ++ ScalaValueClasses()
-
- // Enter all symbols from the scalaShadowing package in the scala package
+
+ // Enter all symbols from the scalaShadowing package in the scala package
for (m <- ScalaShadowingPackageClass.info.decls)
ScalaPackageClass.enter(m)
diff --git a/src/dotty/tools/dotc/core/tasty/PositionPickler.scala b/src/dotty/tools/dotc/core/tasty/PositionPickler.scala
index 4b67bc188..546894a9e 100644
--- a/src/dotty/tools/dotc/core/tasty/PositionPickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/PositionPickler.scala
@@ -13,7 +13,7 @@ import collection.mutable
import TastyBuffer._
import util.Positions._
-class PositionPickler(pickler: TastyPickler, addrsOfTree: tpd.Tree => List[Addr]) {
+class PositionPickler(pickler: TastyPickler, addrOfTree: tpd.Tree => Option[Addr]) {
val buf = new TastyBuffer(5000)
pickler.newSection("Positions", buf)
import buf._
@@ -21,21 +21,6 @@ class PositionPickler(pickler: TastyPickler, addrsOfTree: tpd.Tree => List[Addr]
private val remainingAddrs = new java.util.IdentityHashMap[Tree, Iterator[Addr]]
- def nextTreeAddr(tree: Tree): Option[Addr] = remainingAddrs.get(tree) match {
- case null =>
- addrsOfTree(tree) match {
- case Nil =>
- None
- case addr :: Nil =>
- Some(addr)
- case addrs =>
- remainingAddrs.put(tree, addrs.iterator)
- nextTreeAddr(tree)
- }
- case it: Iterator[_] =>
- if (it.hasNext) Some(it.next) else None
- }
-
def header(addrDelta: Int, hasStartDelta: Boolean, hasEndDelta: Boolean, hasPoint: Boolean) = {
def toInt(b: Boolean) = if (b) 1 else 0
(addrDelta << 3) | (toInt(hasStartDelta) << 2) | (toInt(hasEndDelta) << 1) | toInt(hasPoint)
@@ -60,8 +45,7 @@ class PositionPickler(pickler: TastyPickler, addrsOfTree: tpd.Tree => List[Addr]
*/
def alwaysNeedsPos(x: Positioned) = x match {
case _: WithLazyField[_] // initialPos is inaccurate for trees with lazy field
- | _: Trees.PackageDef[_] => true // package defs might be split into several Tasty files
- case x: Trees.Tree[_] => x.isType // types are unpickled as TypeTrees, so child positions are not available
+ | _: Trees.PackageDef[_] => true // package defs might be split into several Tasty files
case _ => false
}
@@ -69,7 +53,7 @@ class PositionPickler(pickler: TastyPickler, addrsOfTree: tpd.Tree => List[Addr]
case x: Tree @unchecked =>
val pos = if (x.isInstanceOf[MemberDef]) x.pos else x.pos.toSynthetic
if (pos.exists && (pos != x.initialPos.toSynthetic || alwaysNeedsPos(x))) {
- nextTreeAddr(x) match {
+ addrOfTree(x) match {
case Some(addr) =>
//println(i"pickling $x with $pos at $addr")
pickleDeltas(addr.index, pos)
@@ -79,13 +63,15 @@ class PositionPickler(pickler: TastyPickler, addrsOfTree: tpd.Tree => List[Addr]
}
//else if (x.pos.exists) println(i"skipping $x")
x match {
- case x: MemberDef @unchecked =>
+ case x: MemberDef @unchecked =>
for (ann <- x.symbol.annotations) traverse(ann.tree)
case _ =>
}
traverse(x.productIterator)
case xs: TraversableOnce[_] =>
xs.foreach(traverse)
+ case x: Annotation =>
+ traverse(x.tree)
case _ =>
}
traverse(roots)
diff --git a/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
index f9743d9d2..80bd39841 100644
--- a/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
+++ b/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
@@ -71,7 +71,7 @@ Standard-Section: "ASTs" TopLevelStat*
Term = Path
Application
- IDENT NameRef Type // used when ident’s type is not a TermRef
+ IDENT NameRef Type // used when term ident’s type is not a TermRef
SELECT possiblySigned_NameRef qual_Term
NEW cls_Type
SUPER Length this_Term mixinTrait_Type?
@@ -89,6 +89,17 @@ Standard-Section: "ASTs" TopLevelStat*
BIND Length boundName_NameRef patType_Type pat_Term
ALTERNATIVE Length alt_Term*
UNAPPLY Length fun_Term ImplicitArg* pat_Type pat_Term*
+ IDENTtpt NameRef Type // used when type ident's type is not a TypeRef
+ SELECTtpt NameRef qual_Term
+ SINGLETONtpt Path
+ REFINDtpt Length underlying_Term refinement_Stat*
+ APPLIEDtpt Length tycon_Term arg_Term*
+ POLYtpt Length TypeParam* body_Term
+ TYPEBOUNDStpt Length low_Term high_Term
+ ANNOTATEDtpt Length underlying_Term fullAnnotation_Term
+ ANDtpt Length left_Term right_Term
+ ORtpt Length left_Term right_Term
+ BYNAMEtpt underlying_Term
EMPTYTREE
SHARED term_ASTRef
Application = APPLY Length fn_Term arg_Term*
@@ -133,7 +144,7 @@ Standard-Section: "ASTs" TopLevelStat*
APPLIEDtype Length tycon_Type arg_Type*
TYPEBOUNDS Length low_Type high_Type
TYPEALIAS Length alias_Type (COVARIANT | CONTRAVARIANT)?
- ANNOTATED Length underlying_Type fullAnnotation_Term
+ ANNOTATEDtype Length underlying_Type fullAnnotation_Term
ANDtype Length left_Type right_Type
ORtype Length left_Type right_Type
BIND Length boundName_NameRef bounds_Type
@@ -271,19 +282,23 @@ object TastyFormat {
final val CLASSconst = 97
final val ENUMconst = 98
final val BYNAMEtype = 99
- final val NEW = 100
- final val IMPLICITarg = 101
- final val PRIVATEqualified = 102
- final val PROTECTEDqualified = 103
- final val RECtype = 104
+ final val BYNAMEtpt = 100
+ final val NEW = 101
+ final val IMPLICITarg = 102
+ final val PRIVATEqualified = 103
+ final val PROTECTEDqualified = 104
+ final val RECtype = 105
+ final val SINGLETONtpt = 106
final val IDENT = 112
- final val SELECT = 113
- final val TERMREFsymbol = 114
- final val TERMREF = 115
- final val TYPEREFsymbol = 116
- final val TYPEREF = 117
- final val SELFDEF = 118
+ final val IDENTtpt = 113
+ final val SELECT = 114
+ final val SELECTtpt = 115
+ final val TERMREFsymbol = 116
+ final val TERMREF = 117
+ final val TYPEREFsymbol = 118
+ final val TYPEREF = 119
+ final val SELFDEF = 120
final val PACKAGE = 128
final val VALDEF = 129
@@ -293,39 +308,44 @@ object TastyFormat {
final val TYPEPARAM = 133
final val PARAMS = 134
final val PARAM = 136
-
- final val APPLY = 139
- final val TYPEAPPLY = 140
-
- final val TYPED = 143
- final val NAMEDARG = 144
- final val ASSIGN = 145
- final val BLOCK = 146
- final val IF = 147
- final val LAMBDA = 148
- final val MATCH = 149
- final val RETURN = 150
- final val TRY = 151
- final val INLINED = 152
- final val REPEATED = 153
- final val BIND = 154
- final val ALTERNATIVE = 155
- final val UNAPPLY = 156
- final val ANNOTATED = 157
- final val CASEDEF = 158
- final val TEMPLATE = 160
- final val SUPER = 163
- final val SUPERtype = 166
- final val REFINEDtype = 167
- final val APPLIEDtype = 168
- final val TYPEBOUNDS = 169
- final val TYPEALIAS = 170
- final val ANDtype = 171
- final val ORtype = 172
- final val METHODtype = 174
- final val POLYtype = 175
- final val PARAMtype = 176
- final val ANNOTATION = 177
+ final val APPLY = 137
+ final val TYPEAPPLY = 138
+ final val TYPED = 139
+ final val NAMEDARG = 140
+ final val ASSIGN = 141
+ final val BLOCK = 142
+ final val IF = 143
+ final val LAMBDA = 144
+ final val MATCH = 145
+ final val RETURN = 146
+ final val TRY = 147
+ final val INLINED = 148
+ final val REPEATED = 149
+ final val BIND = 150
+ final val ALTERNATIVE = 151
+ final val UNAPPLY = 152
+ final val ANNOTATEDtype = 153
+ final val ANNOTATEDtpt = 154
+ final val CASEDEF = 155
+ final val TEMPLATE = 156
+ final val SUPER = 157
+ final val SUPERtype = 158
+ final val REFINEDtype = 159
+ final val REFINEDtpt = 160
+ final val APPLIEDtype = 161
+ final val APPLIEDtpt = 162
+ final val TYPEBOUNDS = 163
+ final val TYPEBOUNDStpt = 164
+ final val TYPEALIAS = 165
+ final val ANDtype = 166
+ final val ANDtpt = 167
+ final val ORtype = 168
+ final val ORtpt = 169
+ final val METHODtype = 170
+ final val POLYtype = 171
+ final val POLYtpt = 172
+ final val PARAMtype = 173
+ final val ANNOTATION = 174
final val firstSimpleTreeTag = UNITconst
final val firstNatTreeTag = SHARED
@@ -367,7 +387,22 @@ object TastyFormat {
| PRIVATEqualified
| PROTECTEDqualified => true
case _ => false
- }
+ }
+
+ def isTypeTreeTag(tag: Int) = tag match {
+ case IDENTtpt
+ | SELECTtpt
+ | SINGLETONtpt
+ | REFINEDtpt
+ | APPLIEDtpt
+ | POLYtpt
+ | TYPEBOUNDStpt
+ | ANNOTATEDtpt
+ | ANDtpt
+ | ORtpt
+ | BYNAMEtpt => true
+ case _ => false
+ }
def nameTagToString(tag: Int): String = tag match {
case UTF8 => "UTF8"
@@ -429,7 +464,9 @@ object TastyFormat {
case RECtype => "RECtype"
case IDENT => "IDENT"
+ case IDENTtpt => "IDENTtpt"
case SELECT => "SELECT"
+ case SELECTtpt => "SELECTtpt"
case TERMREFsymbol => "TERMREFsymbol"
case TERMREF => "TERMREF"
case TYPEREFsymbol => "TYPEREFsymbol"
@@ -462,7 +499,8 @@ object TastyFormat {
case BIND => "BIND"
case ALTERNATIVE => "ALTERNATIVE"
case UNAPPLY => "UNAPPLY"
- case ANNOTATED => "ANNOTATED"
+ case ANNOTATEDtype => "ANNOTATEDtype"
+ case ANNOTATEDtpt => "ANNOTATEDtpt"
case CASEDEF => "CASEDEF"
case IMPLICITarg => "IMPLICITarg"
case TEMPLATE => "TEMPLATE"
@@ -471,15 +509,23 @@ object TastyFormat {
case SUPER => "SUPER"
case CLASSconst => "CLASSconst"
case ENUMconst => "ENUMconst"
+ case SINGLETONtpt => "SINGLETONtpt"
case SUPERtype => "SUPERtype"
case REFINEDtype => "REFINEDtype"
+ case REFINEDtpt => "REFINEDtpt"
case APPLIEDtype => "APPLIEDtype"
+ case APPLIEDtpt => "APPLIEDtpt"
case TYPEBOUNDS => "TYPEBOUNDS"
+ case TYPEBOUNDStpt => "TYPEBOUNDStpt"
case TYPEALIAS => "TYPEALIAS"
case ANDtype => "ANDtype"
+ case ANDtpt => "ANDtpt"
case ORtype => "ORtype"
+ case ORtpt => "ORtpt"
case BYNAMEtype => "BYNAMEtype"
+ case BYNAMEtpt => "BYNAMEtpt"
case POLYtype => "POLYtype"
+ case POLYtpt => "POLYtpt"
case METHODtype => "METHODtype"
case PARAMtype => "PARAMtype"
case ANNOTATION => "ANNOTATION"
diff --git a/src/dotty/tools/dotc/core/tasty/TastyPickler.scala b/src/dotty/tools/dotc/core/tasty/TastyPickler.scala
index f847dda68..55fe232c0 100644
--- a/src/dotty/tools/dotc/core/tasty/TastyPickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/TastyPickler.scala
@@ -61,7 +61,7 @@ class TastyPickler {
* Note that a tree can have several addresses, if it is shared,
* i.e. accessible from different paths. Any such sharing is undone by pickling.
*/
- var addrsOfTree: tpd.Tree => List[Addr] = (_ => Nil)
+ var addrOfTree: tpd.Tree => Option[Addr] = (_ => None)
/**
* Addresses in TASTY file of symbols, stored by pickling.
diff --git a/src/dotty/tools/dotc/core/tasty/TreeBuffer.scala b/src/dotty/tools/dotc/core/tasty/TreeBuffer.scala
index f2681ecde..67dc6076f 100644
--- a/src/dotty/tools/dotc/core/tasty/TreeBuffer.scala
+++ b/src/dotty/tools/dotc/core/tasty/TreeBuffer.scala
@@ -17,26 +17,20 @@ class TreeBuffer extends TastyBuffer(50000) {
private var delta: Array[Int] = _
private var numOffsets = 0
- private type TreeAddrs = Any // really: Addr | List[Addr]
-
/** A map from trees to the address(es) at which a tree is pickled. There may be several
* such addresses if the tree is shared. To keep the map compact, the value type is a
* disjunction of a single address (which is the common case) and a list of addresses.
*/
- private val treeAddrs = new java.util.IdentityHashMap[Tree, TreeAddrs]
+ private val treeAddrs = new java.util.IdentityHashMap[Tree, Any] // really: Addr | Null
- def registerTreeAddr(tree: Tree) =
- treeAddrs.put(tree,
- treeAddrs.get(tree) match {
- case null => currentAddr
- case x: Addr => x :: currentAddr :: Nil
- case xs: List[_] => xs :+ currentAddr
- })
-
- def addrsOfTree(tree: Tree): List[Addr] = treeAddrs.get(tree) match {
- case null => Nil
- case addr: Addr => addr :: Nil
- case addrs: List[Addr] => addrs
+ def registerTreeAddr(tree: Tree): Addr = treeAddrs.get(tree) match {
+ case null => treeAddrs.put(tree, currentAddr); currentAddr
+ case addr: Addr => addr
+ }
+
+ def addrOfTree(tree: Tree): Option[Addr] = treeAddrs.get(tree) match {
+ case null => None
+ case addr: Addr => Some(addr)
}
private def offset(i: Int): Addr = Addr(offsets(i))
diff --git a/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/src/dotty/tools/dotc/core/tasty/TreePickler.scala
index 98a369f25..1838bc5bb 100644
--- a/src/dotty/tools/dotc/core/tasty/TreePickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/TreePickler.scala
@@ -10,6 +10,7 @@ import Contexts._, Symbols._, Types._, Names._, Constants._, Decorators._, Annot
import collection.mutable
import typer.Inliner
import NameOps._
+import StdNames.nme
import TastyBuffer._
import TypeApplications._
@@ -153,11 +154,6 @@ class TreePickler(pickler: TastyPickler) {
throw ex
}
- def pickleTypeWithPos(tpe: Type, tree: Tree)(implicit ctx: Context): Unit = {
- registerTreeAddr(tree)
- pickleType(tpe)
- }
-
private def pickleNewType(tpe: Type, richTypes: Boolean)(implicit ctx: Context): Unit = try { tpe match {
case AppliedType(tycon, args) =>
writeByte(APPLIEDtype)
@@ -249,7 +245,7 @@ class TreePickler(pickler: TastyPickler) {
writeByte(TYPEBOUNDS)
withLength { pickleType(tpe.lo, richTypes); pickleType(tpe.hi, richTypes) }
case tpe: AnnotatedType =>
- writeByte(ANNOTATED)
+ writeByte(ANNOTATEDtype)
withLength { pickleType(tpe.tpe, richTypes); pickleTree(tpe.annot.tree) }
case tpe: AndOrType =>
writeByte(if (tpe.isAnd) ANDtype else ORtype)
@@ -306,7 +302,7 @@ class TreePickler(pickler: TastyPickler) {
}
def pickleTpt(tpt: Tree)(implicit ctx: Context): Unit =
- pickleTypeWithPos(tpt.tpe, tpt) // TODO correlate with original when generating positions
+ pickleTree(tpt)
def pickleTreeUnlessEmpty(tree: Tree)(implicit ctx: Context): Unit =
if (!tree.isEmpty) pickleTree(tree)
@@ -346,181 +342,226 @@ class TreePickler(pickler: TastyPickler) {
stats.foreach(stat => if (!stat.isEmpty) pickleTree(stat))
}
- def pickleTree(tree: Tree)(implicit ctx: Context): Unit = try {
- registerTreeAddr(tree)
- tree match {
- case tree if tree.isType =>
- pickleTpt(tree)
- case Ident(name) =>
- tree.tpe match {
- case tp: TermRef => pickleType(tp)
- case _ =>
- writeByte(IDENT)
- pickleName(name)
- pickleType(tree.tpe)
- }
- case This(_) =>
- pickleType(tree.tpe)
- case Select(qual, name) =>
- writeByte(SELECT)
- val realName = tree.tpe match {
- case tp: NamedType if tp.name.isShadowedName => tp.name
- case _ => name
- }
- val sig = tree.tpe.signature
- if (sig == Signature.NotAMethod) pickleName(realName)
- else pickleNameAndSig(realName, sig)
- pickleTree(qual)
- case Apply(fun, args) =>
- writeByte(APPLY)
- withLength {
- pickleTree(fun)
- args.foreach(pickleTree)
- }
- case TypeApply(fun, args) =>
- writeByte(TYPEAPPLY)
- withLength {
- pickleTree(fun)
- args.foreach(pickleTpt)
- }
- case Literal(const1) =>
- pickleConstant {
+ def pickleTree(tree: Tree)(implicit ctx: Context): Unit = {
+ val addr = registerTreeAddr(tree)
+ if (addr != currentAddr) {
+ writeByte(SHARED)
+ writeRef(addr)
+ }
+ else
+ try tree match {
+ case Ident(name) =>
tree.tpe match {
- case ConstantType(const2) => const2
- case _ => const1
+ case tp: TermRef if name != nme.WILDCARD =>
+ // wildcards are pattern bound, need to be preserved as ids.
+ pickleType(tp)
+ case _ =>
+ writeByte(if (tree.isType) IDENTtpt else IDENT)
+ pickleName(name)
+ pickleType(tree.tpe)
}
- }
- case Super(qual, mix) =>
- writeByte(SUPER)
- withLength {
- pickleTree(qual);
- if (!mix.isEmpty) {
- val SuperType(_, mixinType) = tree.tpe
- pickleType(mixinType)
+ case This(_) =>
+ pickleType(tree.tpe)
+ case Select(qual, name) =>
+ writeByte(if (name.isTypeName) SELECTtpt else SELECT)
+ val realName = tree.tpe match {
+ case tp: NamedType if tp.name.isShadowedName => tp.name
+ case _ => name
}
- }
- case New(tpt) =>
- writeByte(NEW)
- pickleTpt(tpt)
- case Typed(expr, tpt) =>
- writeByte(TYPED)
- withLength { pickleTree(expr); pickleTpt(tpt) }
- case NamedArg(name, arg) =>
- writeByte(NAMEDARG)
- withLength { pickleName(name); pickleTree(arg) }
- case Assign(lhs, rhs) =>
- writeByte(ASSIGN)
- withLength { pickleTree(lhs); pickleTree(rhs) }
- case Block(stats, expr) =>
- writeByte(BLOCK)
- stats.foreach(preRegister)
- withLength { pickleTree(expr); stats.foreach(pickleTree) }
- case If(cond, thenp, elsep) =>
- writeByte(IF)
- withLength{ pickleTree(cond); pickleTree(thenp); pickleTree(elsep) }
- case Closure(env, meth, tpt) =>
- writeByte(LAMBDA)
- assert(env.isEmpty)
- withLength{
- pickleTree(meth)
- if (tpt.tpe.exists) pickleTpt(tpt)
- }
- case Match(selector, cases) =>
- writeByte(MATCH)
- withLength { pickleTree(selector); cases.foreach(pickleTree) }
- case CaseDef(pat, guard, rhs) =>
- writeByte(CASEDEF)
- withLength { pickleTree(pat); pickleTree(rhs); pickleTreeUnlessEmpty(guard) }
- case Return(expr, from) =>
- writeByte(RETURN)
- withLength { pickleSymRef(from.symbol); pickleTreeUnlessEmpty(expr) }
- case Try(block, cases, finalizer) =>
- writeByte(TRY)
- withLength { pickleTree(block); cases.foreach(pickleTree); pickleTreeUnlessEmpty(finalizer) }
- case SeqLiteral(elems, elemtpt) =>
- writeByte(REPEATED)
- withLength { pickleTree(elemtpt); elems.foreach(pickleTree) }
- case Inlined(call, bindings, expansion) =>
- writeByte(INLINED)
- bindings.foreach(preRegister)
- withLength { pickleTree(call); pickleTree(expansion); bindings.foreach(pickleTree) }
- case Bind(name, body) =>
- registerDef(tree.symbol)
- writeByte(BIND)
- withLength { pickleName(name); pickleType(tree.symbol.info); pickleTree(body) }
- case Alternative(alts) =>
- writeByte(ALTERNATIVE)
- withLength { alts.foreach(pickleTree) }
- case UnApply(fun, implicits, patterns) =>
- writeByte(UNAPPLY)
- withLength {
- pickleTree(fun)
- for (implicitArg <- implicits) {
- writeByte(IMPLICITarg)
- pickleTree(implicitArg)
+ val sig = tree.tpe.signature
+ if (sig == Signature.NotAMethod) pickleName(realName)
+ else pickleNameAndSig(realName, sig)
+ pickleTree(qual)
+ case Apply(fun, args) =>
+ writeByte(APPLY)
+ withLength {
+ pickleTree(fun)
+ args.foreach(pickleTree)
}
- pickleType(tree.tpe)
- patterns.foreach(pickleTree)
- }
- case tree: ValDef =>
- pickleDef(VALDEF, tree.symbol, tree.tpt, tree.rhs)
- case tree: DefDef =>
- def pickleAllParams = {
- pickleParams(tree.tparams)
- for (vparams <- tree.vparamss) {
- writeByte(PARAMS)
- withLength { pickleParams(vparams) }
+ case TypeApply(fun, args) =>
+ writeByte(TYPEAPPLY)
+ withLength {
+ pickleTree(fun)
+ args.foreach(pickleTpt)
}
- }
- pickleDef(DEFDEF, tree.symbol, tree.tpt, tree.rhs, pickleAllParams)
- case tree: TypeDef =>
- pickleDef(TYPEDEF, tree.symbol, tree.rhs)
- case tree: Template =>
- registerDef(tree.symbol)
- writeByte(TEMPLATE)
- val (params, rest) = tree.body partition {
- case stat: TypeDef => stat.symbol is Flags.Param
- case stat: ValOrDefDef =>
- stat.symbol.is(Flags.ParamAccessor) && !stat.symbol.isSetter
- case _ => false
- }
- withLength {
- pickleParams(params)
- tree.parents.foreach(pickleTree)
- val cinfo @ ClassInfo(_, _, _, _, selfInfo) = tree.symbol.owner.info
- if ((selfInfo ne NoType) || !tree.self.isEmpty) {
- writeByte(SELFDEF)
- pickleName(tree.self.name)
- if (!tree.self.isEmpty) registerTreeAddr(tree.self.tpt)
- pickleType {
- cinfo.selfInfo match {
- case sym: Symbol => sym.info
- case tp: Type => tp
+ case Literal(const1) =>
+ pickleConstant {
+ tree.tpe match {
+ case ConstantType(const2) => const2
+ case _ => const1
+ }
+ }
+ case Super(qual, mix) =>
+ writeByte(SUPER)
+ withLength {
+ pickleTree(qual);
+ if (!mix.isEmpty) {
+ val SuperType(_, mixinType) = tree.tpe
+ pickleType(mixinType)
+ }
+ }
+ case New(tpt) =>
+ writeByte(NEW)
+ pickleTpt(tpt)
+ case Typed(expr, tpt) =>
+ writeByte(TYPED)
+ withLength { pickleTree(expr); pickleTpt(tpt) }
+ case NamedArg(name, arg) =>
+ writeByte(NAMEDARG)
+ withLength { pickleName(name); pickleTree(arg) }
+ case Assign(lhs, rhs) =>
+ writeByte(ASSIGN)
+ withLength { pickleTree(lhs); pickleTree(rhs) }
+ case Block(stats, expr) =>
+ writeByte(BLOCK)
+ stats.foreach(preRegister)
+ withLength { pickleTree(expr); stats.foreach(pickleTree) }
+ case If(cond, thenp, elsep) =>
+ writeByte(IF)
+ withLength { pickleTree(cond); pickleTree(thenp); pickleTree(elsep) }
+ case Closure(env, meth, tpt) =>
+ writeByte(LAMBDA)
+ assert(env.isEmpty)
+ withLength {
+ pickleTree(meth)
+ if (tpt.tpe.exists) pickleTpt(tpt)
+ }
+ case Match(selector, cases) =>
+ writeByte(MATCH)
+ withLength { pickleTree(selector); cases.foreach(pickleTree) }
+ case CaseDef(pat, guard, rhs) =>
+ writeByte(CASEDEF)
+ withLength { pickleTree(pat); pickleTree(rhs); pickleTreeUnlessEmpty(guard) }
+ case Return(expr, from) =>
+ writeByte(RETURN)
+ withLength { pickleSymRef(from.symbol); pickleTreeUnlessEmpty(expr) }
+ case Try(block, cases, finalizer) =>
+ writeByte(TRY)
+ withLength { pickleTree(block); cases.foreach(pickleTree); pickleTreeUnlessEmpty(finalizer) }
+ case SeqLiteral(elems, elemtpt) =>
+ writeByte(REPEATED)
+ withLength { pickleTree(elemtpt); elems.foreach(pickleTree) }
+ case Inlined(call, bindings, expansion) =>
+ writeByte(INLINED)
+ bindings.foreach(preRegister)
+ withLength { pickleTree(call); pickleTree(expansion); bindings.foreach(pickleTree) }
+ case Bind(name, body) =>
+ registerDef(tree.symbol)
+ writeByte(BIND)
+ withLength { pickleName(name); pickleType(tree.symbol.info); pickleTree(body) }
+ case Alternative(alts) =>
+ writeByte(ALTERNATIVE)
+ withLength { alts.foreach(pickleTree) }
+ case UnApply(fun, implicits, patterns) =>
+ writeByte(UNAPPLY)
+ withLength {
+ pickleTree(fun)
+ for (implicitArg <- implicits) {
+ writeByte(IMPLICITarg)
+ pickleTree(implicitArg)
+ }
+ pickleType(tree.tpe)
+ patterns.foreach(pickleTree)
+ }
+ case tree: ValDef =>
+ pickleDef(VALDEF, tree.symbol, tree.tpt, tree.rhs)
+ case tree: DefDef =>
+ def pickleAllParams = {
+ pickleParams(tree.tparams)
+ for (vparams <- tree.vparamss) {
+ writeByte(PARAMS)
+ withLength { pickleParams(vparams) }
+ }
+ }
+ pickleDef(DEFDEF, tree.symbol, tree.tpt, tree.rhs, pickleAllParams)
+ case tree: TypeDef =>
+ pickleDef(TYPEDEF, tree.symbol, tree.rhs)
+ case tree: Template =>
+ registerDef(tree.symbol)
+ writeByte(TEMPLATE)
+ val (params, rest) = tree.body partition {
+ case stat: TypeDef => stat.symbol is Flags.Param
+ case stat: ValOrDefDef =>
+ stat.symbol.is(Flags.ParamAccessor) && !stat.symbol.isSetter
+ case _ => false
+ }
+ withLength {
+ pickleParams(params)
+ tree.parents.foreach(pickleTree)
+ val cinfo @ ClassInfo(_, _, _, _, selfInfo) = tree.symbol.owner.info
+ if ((selfInfo ne NoType) || !tree.self.isEmpty) {
+ writeByte(SELFDEF)
+ pickleName(tree.self.name)
+
+ if (!tree.self.tpt.isEmpty) pickleTree(tree.self.tpt)
+ else {
+ if (!tree.self.isEmpty) registerTreeAddr(tree.self)
+ pickleType {
+ cinfo.selfInfo match {
+ case sym: Symbol => sym.info
+ case tp: Type => tp
+ }
+ }
}
}
+ pickleStats(tree.constr :: rest)
}
- pickleStats(tree.constr :: rest)
- }
- case Import(expr, selectors) =>
- writeByte(IMPORT)
- withLength {
- pickleTree(expr)
- selectors foreach {
- case Thicket((from @ Ident(_)) :: (to @ Ident(_)) :: Nil) =>
- pickleSelector(IMPORTED, from)
- pickleSelector(RENAMED, to)
- case id @ Ident(_) =>
- pickleSelector(IMPORTED, id)
+ case Import(expr, selectors) =>
+ writeByte(IMPORT)
+ withLength {
+ pickleTree(expr)
+ selectors foreach {
+ case Thicket((from @ Ident(_)) :: (to @ Ident(_)) :: Nil) =>
+ pickleSelector(IMPORTED, from)
+ pickleSelector(RENAMED, to)
+ case id @ Ident(_) =>
+ pickleSelector(IMPORTED, id)
+ }
}
- }
- case PackageDef(pid, stats) =>
- writeByte(PACKAGE)
- withLength { pickleType(pid.tpe); pickleStats(stats) }
- }}
- catch {
- case ex: AssertionError =>
- println(i"error when pickling tree $tree")
- throw ex
+ case PackageDef(pid, stats) =>
+ writeByte(PACKAGE)
+ withLength { pickleType(pid.tpe); pickleStats(stats) }
+ case tree: TypeTree =>
+ pickleType(tree.tpe)
+ case SingletonTypeTree(ref) =>
+ writeByte(SINGLETONtpt)
+ pickleTree(ref)
+ case RefinedTypeTree(parent, refinements) =>
+ if (refinements.isEmpty) pickleTree(parent)
+ else {
+ val refineCls = refinements.head.symbol.owner.asClass
+ pickledTypes.put(refineCls.typeRef, currentAddr)
+ writeByte(REFINEDtpt)
+ refinements.foreach(preRegister)
+ withLength { pickleTree(parent); refinements.foreach(pickleTree) }
+ }
+ case AppliedTypeTree(tycon, args) =>
+ writeByte(APPLIEDtpt)
+ withLength { pickleTree(tycon); args.foreach(pickleTree(_)) }
+ case AndTypeTree(tp1, tp2) =>
+ writeByte(ANDtpt)
+ withLength { pickleTree(tp1); pickleTree(tp2) }
+ case OrTypeTree(tp1, tp2) =>
+ writeByte(ORtpt)
+ withLength { pickleTree(tp1); pickleTree(tp2) }
+ case ByNameTypeTree(tp) =>
+ writeByte(BYNAMEtpt)
+ pickleTree(tp)
+ case Annotated(tree, annot) =>
+ writeByte(ANNOTATEDtpt)
+ withLength { pickleTree(tree); pickleTree(annot.tree) }
+ case PolyTypeTree(tparams, body) =>
+ writeByte(POLYtpt)
+ withLength { pickleParams(tparams); pickleTree(body) }
+ case TypeBoundsTree(lo, hi) =>
+ writeByte(TYPEBOUNDStpt)
+ withLength { pickleTree(lo); pickleTree(hi) }
+ }
+ catch {
+ case ex: AssertionError =>
+ println(i"error when pickling tree $tree")
+ throw ex
+ }
}
def pickleSelector(tag: Int, id: untpd.Ident)(implicit ctx: Context): Unit = {
diff --git a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
index 90f718402..1f0bbca19 100644
--- a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
@@ -256,7 +256,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
else if (nextByte == CONTRAVARIANT) { readByte(); -1 }
else 0
TypeAlias(alias, variance)
- case ANNOTATED =>
+ case ANNOTATEDtype =>
AnnotatedType(readType(), Annotation(readTerm()))
case ANDtype =>
AndType(readType(), readType())
@@ -368,7 +368,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
private def readPackageRef()(implicit ctx: Context): TermSymbol = {
val name = readName()
- if (name == nme.ROOT) defn.RootPackage
+ if (name == nme.ROOT || name == nme.ROOTPKG) defn.RootPackage
else if (name == nme.EMPTY_PACKAGE) defn.EmptyPackageVal
else ctx.requiredPackage(name)
}
@@ -389,11 +389,11 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
if (owner.isClass) lctx.setScope(owner.unforcedDecls) else lctx.setNewScope
}
- private def normalizeFlags(tag: Int, givenFlags: FlagSet, name: Name, isAbstractType: Boolean, rhsIsEmpty: Boolean)(implicit ctx: Context): FlagSet = {
+ private def normalizeFlags(tag: Int, givenFlags: FlagSet, name: Name, isAbsType: Boolean, rhsIsEmpty: Boolean)(implicit ctx: Context): FlagSet = {
val lacksDefinition =
rhsIsEmpty &&
name.isTermName && !name.isConstructorName && !givenFlags.is(ParamOrAccessor) ||
- isAbstractType
+ isAbsType
var flags = givenFlags
if (lacksDefinition && tag != PARAM) flags |= Deferred
if (tag == DEFDEF) flags |= Method
@@ -407,6 +407,17 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
flags
}
+ def isAbstractType(ttag: Int)(implicit ctx: Context): Boolean = nextUnsharedTag match {
+ case POLYtpt =>
+ val rdr = fork
+ rdr.reader.readByte() // tag
+ rdr.reader.readNat() // length
+ rdr.skipParams() // tparams
+ rdr.isAbstractType(rdr.nextUnsharedTag)
+ case TYPEBOUNDS | TYPEBOUNDStpt => true
+ case _ => false
+ }
+
/** Create symbol of definition node and enter in symAtAddr map
* @return the created symbol
*/
@@ -433,7 +444,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
if (tag == TYPEDEF || tag == TYPEPARAM) name = name.toTypeName
skipParams()
val ttag = nextUnsharedTag
- val isAbstractType = ttag == TYPEBOUNDS
+ val isAbsType = isAbstractType(ttag)
val isClass = ttag == TEMPLATE
val templateStart = currentAddr
skipTree() // tpt
@@ -447,7 +458,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
case _ => EmptyFlags
}
pickling.println(i"creating symbol $name at $start with flags $givenFlags")
- val flags = normalizeFlags(tag, givenFlags | nameFlags(rawName), name, isAbstractType, rhsIsEmpty)
+ val flags = normalizeFlags(tag, givenFlags | nameFlags(rawName), name, isAbsType, rhsIsEmpty)
def adjustIfModule(completer: LazyType) =
if (flags is Module) ctx.adjustModuleCompleter(completer, name) else completer
val sym =
@@ -623,11 +634,6 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
val tag = readByte()
val end = readEnd()
- def readParams[T <: MemberDef](tag: Int)(implicit ctx: Context): List[T] = {
- fork.indexParams(tag)(localContext(sym))
- readIndexedParams(tag)
- }
-
def readParamss(implicit ctx: Context): List[List[ValDef]] = {
collectWhile(nextByte == PARAMS) {
readByte()
@@ -849,9 +855,14 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
def readIndexedParams[T <: MemberDef](tag: Int)(implicit ctx: Context): List[T] =
collectWhile(nextByte == tag) { readIndexedDef().asInstanceOf[T] }
-// ------ Reading terms -----------------------------------------------------
+ def readParams[T <: MemberDef](tag: Int)(implicit ctx: Context): List[T] = {
+ fork.indexParams(tag)
+ readIndexedParams(tag)
+ }
- def readTerm()(implicit ctx: Context): Tree = {
+// ------ Reading trees -----------------------------------------------------
+
+ def readTerm()(implicit ctx: Context): Tree = { // TODO: rename to readTree
val start = currentAddr
val tag = readByte()
pickling.println(s"reading term ${astTagToString(tag)} at $start")
@@ -859,34 +870,44 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
def readPathTerm(): Tree = {
goto(start)
readType() match {
+ case path: TypeRef => TypeTree(path)
case path: TermRef => ref(path)
case path: ThisType => This(path.cls)
case path: ConstantType => Literal(path.value)
}
}
+ def completeSelect(name: Name, tpf: Type => Type): Select = {
+ val localCtx =
+ if (name == nme.CONSTRUCTOR) ctx.addMode(Mode.InSuperCall) else ctx
+ val qual = readTerm()(localCtx)
+ val unshadowed = if (name.isShadowedName) name.revertShadowed else name
+ untpd.Select(qual, unshadowed).withType(tpf(qual.tpe.widenIfUnstable))
+ }
+
def readSimpleTerm(): Tree = tag match {
+ case SHARED =>
+ forkAt(readAddr()).readTerm()
case IDENT =>
untpd.Ident(readName()).withType(readType())
+ case IDENTtpt =>
+ untpd.Ident(readName().toTypeName).withType(readType())
case SELECT =>
- def readQual(name: Name) = {
- val localCtx =
- if (name == nme.CONSTRUCTOR) ctx.addMode(Mode.InSuperCall) else ctx
- readTerm()(localCtx)
- }
- def readRest(name: Name, sig: Signature) = {
- val unshadowed = if (name.isShadowedName) name.revertShadowed else name
- val qual = readQual(name)
- untpd.Select(qual, unshadowed)
- .withType(TermRef.withSig(qual.tpe.widenIfUnstable, name.asTermName, sig))
- }
+ def readRest(name: Name, sig: Signature) =
+ completeSelect(name, TermRef.withSig(_, name.asTermName, sig))
readNameSplitSig match {
case name: Name => readRest(name, Signature.NotAMethod)
case (name: Name, sig: Signature) => readRest(name, sig)
}
-
+ case SELECTtpt =>
+ val name = readName().toTypeName
+ completeSelect(name, TypeRef(_, name))
case NEW =>
New(readTpt())
+ case SINGLETONtpt =>
+ SingletonTypeTree(readTerm())
+ case BYNAMEtpt =>
+ ByNameTypeTree(readTpt())
case _ =>
readPathTerm()
}
@@ -894,10 +915,15 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
def readLengthTerm(): Tree = {
val end = readEnd()
+ def localNonClassCtx = {
+ val ctx1 = ctx.fresh.setNewScope
+ if (ctx.owner.isClass) ctx1.setOwner(ctx1.newLocalDummy(ctx.owner)) else ctx1
+ }
+
def readBlock(mkTree: (List[Tree], Tree) => Tree): Tree = {
val exprReader = fork
skipTree()
- val localCtx = ctx.fresh.setNewScope
+ val localCtx = localNonClassCtx
val stats = readStats(ctx.owner, end)(localCtx)
val expr = exprReader.readTerm()(localCtx)
mkTree(stats, expr)
@@ -937,7 +963,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
case BLOCK =>
readBlock(Block)
case INLINED =>
- val call = setPos(currentAddr, TypeTree(readType()))
+ val call = readTerm()
readBlock((defs, expr) => Inlined(call, defs.asInstanceOf[List[MemberDef]], expr))
case IF =>
If(readTerm(), readTerm(), readTerm())
@@ -974,6 +1000,28 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
val patType = readType()
val argPats = until(end)(readTerm())
UnApply(fn, implicitArgs, argPats, patType)
+ case REFINEDtpt =>
+ val refineCls = ctx.newCompleteClassSymbol(
+ ctx.owner, tpnme.REFINE_CLASS, Fresh, parents = Nil)
+ typeAtAddr(start) = refineCls.typeRef
+ val parent = readTpt()
+ val refinements = readStats(refineCls, end)(localContext(refineCls))
+ RefinedTypeTree(parent, refinements, refineCls)
+ case APPLIEDtpt =>
+ AppliedTypeTree(readTpt(), until(end)(readTpt()))
+ case ANDtpt =>
+ AndTypeTree(readTpt(), readTpt())
+ case ORtpt =>
+ OrTypeTree(readTpt(), readTpt())
+ case ANNOTATEDtpt =>
+ Annotated(readTpt(), readTerm())
+ case POLYtpt =>
+ val localCtx = localNonClassCtx
+ val tparams = readParams[TypeDef](TYPEPARAM)(localCtx)
+ val body = readTpt()(localCtx)
+ PolyTypeTree(tparams, body)
+ case TYPEBOUNDStpt =>
+ TypeBoundsTree(readTpt(), readTpt())
case _ =>
readPathTerm()
}
@@ -986,11 +1034,13 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
setPos(start, tree)
}
- def readTpt()(implicit ctx: Context) = {
- val start = currentAddr
- val tp = readType()
- if (tp.exists) setPos(start, TypeTree(tp)) else EmptyTree
- }
+ def readTpt()(implicit ctx: Context) =
+ if (isTypeTreeTag(nextUnsharedTag)) 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(nextByte == CASEDEF && currentAddr != end) { readCase()(ctx.fresh.setNewScope) }
diff --git a/src/dotty/tools/dotc/printing/PlainPrinter.scala b/src/dotty/tools/dotc/printing/PlainPrinter.scala
index 785f57897..06d44e301 100644
--- a/src/dotty/tools/dotc/printing/PlainPrinter.scala
+++ b/src/dotty/tools/dotc/printing/PlainPrinter.scala
@@ -231,9 +231,10 @@ class PlainPrinter(_ctx: Context) extends Printer {
protected def trimPrefix(text: Text) =
text.stripPrefix(objectPrefix).stripPrefix(packagePrefix)
- protected def selectionString(tp: NamedType) =
- if (tp.currentSymbol.exists) nameString(tp.symbol)
- else nameString(tp.name)
+ protected def selectionString(tp: NamedType) = {
+ val sym = if (homogenizedView) tp.symbol else tp.currentSymbol
+ if (sym.exists) nameString(sym) else nameString(tp.name)
+ }
/** The string representation of this type used as a prefix */
protected def toTextRef(tp: SingletonType): Text = controlled {
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index 39a21b17b..4818c6eee 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -21,6 +21,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
/** A stack of enclosing DefDef, TypeDef, or ClassDef, or ModuleDefs nodes */
private var enclosingDef: untpd.Tree = untpd.EmptyTree
private var myCtx: Context = _ctx
+ private var printPos = ctx.settings.Yprintpos.value
override protected[this] implicit def ctx: Context = myCtx
def withEnclosingDef(enclDef: Tree[_ >: Untyped])(op: => Text): Text = {
@@ -35,6 +36,18 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}
}
+ def inPattern(op: => Text): Text = {
+ val savedCtx = myCtx
+ myCtx = ctx.addMode(Mode.Pattern)
+ try op finally myCtx = savedCtx
+ }
+
+ def withoutPos(op: => Text): Text = {
+ val savedPrintPos = printPos
+ printPos = false
+ try op finally printPos = savedPrintPos
+ }
+
private def enclDefIsClass = enclosingDef match {
case owner: TypeDef[_] => owner.isClassDef
case owner: untpd.ModuleDef => true
@@ -134,6 +147,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
return toTextParents(tp.parentsWithArgs) ~ "{...}"
case JavaArrayType(elemtp) =>
return toText(elemtp) ~ "[]"
+ case tp: AnnotatedType if homogenizedView =>
+ withoutPos(super.toText(tp))
case tp: SelectionProto =>
return "?{ " ~ toText(tp.name) ~ (" " provided !tp.name.decode.last.isLetterOrDigit) ~
": " ~ toText(tp.memberProto) ~ " }"
@@ -249,7 +264,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}
def nameIdText(tree: untpd.NameTree): Text =
- toText(tree.name) ~ idText(tree)
+ if (tree.hasType && tree.symbol.exists) nameString(tree.symbol)
+ else toText(tree.name) ~ idText(tree)
def toTextTemplate(impl: Template, ofNew: Boolean = false): Text = {
val Template(constr @ DefDef(_, tparams, vparamss, _, _), parents, self, _) = impl
@@ -284,7 +300,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
case tp: NamedType if name != nme.WILDCARD =>
val pre = if (tp.symbol is JavaStatic) tp.prefix.widen else tp.prefix
toTextPrefix(pre) ~ selectionString(tp)
- case _ => toText(name)
+ case _ =>
+ toText(name)
}
case tree @ Select(qual, name) =>
if (qual.isType) toTextLocal(qual) ~ "#" ~ toText(name)
@@ -337,7 +354,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
if (sel.isEmpty) blockText(cases)
else changePrec(GlobalPrec) { toText(sel) ~ " match " ~ blockText(cases) }
case CaseDef(pat, guard, body) =>
- "case " ~ toText(pat) ~ optText(guard)(" if " ~ _) ~ " => " ~ caseBlockText(body)
+ "case " ~ inPattern(toText(pat)) ~ optText(guard)(" if " ~ _) ~ " => " ~ caseBlockText(body)
case Return(expr, from) =>
changePrec(GlobalPrec) { "return" ~ optText(expr)(" " ~ _) }
case Try(expr, cases, finalizer) =>
@@ -519,22 +536,40 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
case _ =>
tree.fallbackToText(this)
}
+
var txt = toTextCore(tree)
+
+ def suppressTypes =
+ tree.isType || tree.isDef || // don't print types of types or defs
+ homogenizedView && ctx.mode.is(Mode.Pattern)
+ // When comparing pickled info, disregard types of patterns.
+ // The reason is that GADT matching can rewrite types of pattern trees
+ // without changing the trees themselves. (see Typer.typedCase.indexPatterns.transform).
+ // But then pickling and unpickling the original trees will yield trees
+ // with the original types before they are rewritten, which causes a discrepancy.
+
+ def suppressPositions = tree match {
+ case _: WithoutTypeOrPos[_] | _: TypeTree => true // TypeTrees never have an interesting position
+ case _ => false
+ }
+
if (ctx.settings.printtypes.value && tree.hasType) {
- val tp = tree.typeOpt match {
+ // add type to term nodes; replace type nodes with their types unless -Yprintpos is also set.
+ def tp = tree.typeOpt match {
case tp: TermRef if tree.isInstanceOf[RefTree] && !tp.denot.isOverloaded => tp.underlying
case tp => tp
}
- if (tree.isType) txt = toText(tp)
- else if (!tree.isDef) txt = ("<" ~ txt ~ ":" ~ toText(tp) ~ ">").close
+ if (!suppressTypes)
+ txt = ("<" ~ txt ~ ":" ~ toText(tp) ~ ">").close
+ else if (tree.isType && !homogenizedView)
+ txt = toText(tp)
}
- else if (homogenizedView && tree.isType)
- txt = toText(tree.typeOpt)
- if (ctx.settings.Yprintpos.value && !tree.isInstanceOf[WithoutTypeOrPos[_]]) {
+ if (printPos && !suppressPositions) {
+ // add positions
val pos =
if (homogenizedView && !tree.isInstanceOf[MemberDef]) tree.pos.toSynthetic
else tree.pos
- val clsStr = "" // DEBUG: if (tree.isType) tree.getClass.toString else ""
+ val clsStr = ""//if (tree.isType) tree.getClass.toString else ""
txt = (txt ~ "@" ~ pos.toString ~ clsStr).close
}
tree match {
diff --git a/src/dotty/tools/dotc/transform/Pickler.scala b/src/dotty/tools/dotc/transform/Pickler.scala
index fc70ac4f2..2fb85b6c0 100644
--- a/src/dotty/tools/dotc/transform/Pickler.scala
+++ b/src/dotty/tools/dotc/transform/Pickler.scala
@@ -46,10 +46,10 @@ class Pickler extends Phase {
val treePkl = pickler.treePkl
treePkl.pickle(tree :: Nil)
treePkl.compactify()
- pickler.addrsOfTree = treePkl.buf.addrsOfTree
+ pickler.addrOfTree = treePkl.buf.addrOfTree
pickler.addrOfSym = treePkl.addrOfSym
if (tree.pos.exists)
- new PositionPickler(pickler, treePkl.buf.addrsOfTree).picklePositions(tree :: Nil)
+ new PositionPickler(pickler, treePkl.buf.addrOfTree).picklePositions(tree :: Nil)
def rawBytes = // not needed right now, but useful to print raw format.
pickler.assembleParts().iterator.grouped(10).toList.zipWithIndex.map {
diff --git a/src/dotty/tools/dotc/transform/PostTyper.scala b/src/dotty/tools/dotc/transform/PostTyper.scala
index 7e51635e5..1ed47d92e 100644
--- a/src/dotty/tools/dotc/transform/PostTyper.scala
+++ b/src/dotty/tools/dotc/transform/PostTyper.scala
@@ -175,7 +175,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran
Checking.checkRealizable(qual.tpe, qual.pos.focus)
super.transform(tree)
}
- else
+ else
transformSelect(paramFwd.adaptRef(fixSignature(tree)), Nil)
case tree: Super =>
if (ctx.owner.enclosingMethod.isInlineMethod)
diff --git a/tests/pickling/annot.scala b/tests/pickling/annot.scala
new file mode 100644
index 000000000..d20a6cbf4
--- /dev/null
+++ b/tests/pickling/annot.scala
@@ -0,0 +1,12 @@
+trait Type
+class RefinedType extends Type
+
+
+object TestAnnot {
+ def toText(tp: Type) = tp match {
+ case tp: RefinedType =>
+ val parent :: (refined: List[RefinedType @unchecked]) = ???
+ ???
+ }
+ val xs: List[RefinedType @unchecked] = ???
+}
diff --git a/tests/pickling/pickleTypes.scala b/tests/pickling/pickleTypes.scala
new file mode 100644
index 000000000..ef322816a
--- /dev/null
+++ b/tests/pickling/pickleTypes.scala
@@ -0,0 +1,13 @@
+object pickleTypes {
+
+ abstract class C { type T; val x: T; def f: T; def g(y: T): T; def h[U](z: U, y: T): U }
+
+ val x1: Int = ???
+ val x2: List[List[Int]] = ???
+ val x3: C { type T <: C } = ???
+ val x4: C { type T = Int; val x: Int } = ???
+ val x5: C { type T = String; def f: String; def g(y: String): String } = ???
+ val x6: C { type T = String; def f: String; def g(y: String): String; def h[U](z: U, y: T): U } = ???
+
+
+}
diff --git a/tests/pickling/simple.scala b/tests/pickling/simple.scala
new file mode 100644
index 000000000..243b41117
--- /dev/null
+++ b/tests/pickling/simple.scala
@@ -0,0 +1,6 @@
+object Simple {}
+/*class Simple {
+ val x = 3
+ val y: String = ""
+}*/
+