diff options
Diffstat (limited to 'src/dotty/tools')
-rw-r--r-- | src/dotty/tools/dotc/ast/tpd.scala | 10 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Definitions.scala | 8 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/PositionPickler.scala | 26 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/TastyFormat.scala | 142 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/TastyPickler.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/TreeBuffer.scala | 24 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/TreePickler.scala | 387 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 114 | ||||
-rw-r--r-- | src/dotty/tools/dotc/printing/PlainPrinter.scala | 7 | ||||
-rw-r--r-- | src/dotty/tools/dotc/printing/RefinedPrinter.scala | 55 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/Pickler.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/PostTyper.scala | 2 |
12 files changed, 469 insertions, 312 deletions
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) |