aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/syntax-summary.txt4
-rw-r--r--src/dotty/tools/backend/jvm/DottyBackendInterface.scala4
-rw-r--r--src/dotty/tools/dotc/ast/Desugar.scala7
-rw-r--r--src/dotty/tools/dotc/ast/TreeInfo.scala17
-rw-r--r--src/dotty/tools/dotc/ast/Trees.scala41
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala13
-rw-r--r--src/dotty/tools/dotc/ast/untpd.scala29
-rw-r--r--src/dotty/tools/dotc/core/StdNames.scala6
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala5
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala2
-rw-r--r--src/dotty/tools/dotc/core/Types.scala10
-rw-r--r--src/dotty/tools/dotc/core/classfile/ClassfileParser.scala2
-rw-r--r--src/dotty/tools/dotc/core/tasty/PositionPickler.scala26
-rw-r--r--src/dotty/tools/dotc/core/tasty/TastyFormat.scala153
-rw-r--r--src/dotty/tools/dotc/core/tasty/TastyPickler.scala11
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreeBuffer.scala27
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreePickler.scala398
-rw-r--r--src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala132
-rw-r--r--src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala24
-rw-r--r--src/dotty/tools/dotc/parsing/JavaParsers.scala9
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala33
-rw-r--r--src/dotty/tools/dotc/printing/PlainPrinter.scala12
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala82
-rw-r--r--src/dotty/tools/dotc/transform/Erasure.scala4
-rw-r--r--src/dotty/tools/dotc/transform/Pickler.scala4
-rw-r--r--src/dotty/tools/dotc/transform/PostTyper.scala2
-rw-r--r--src/dotty/tools/dotc/transform/SuperAccessors.scala6
-rw-r--r--src/dotty/tools/dotc/transform/TreeTransform.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Inliner.scala36
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala18
-rw-r--r--src/dotty/tools/dotc/typer/TypeAssigner.scala19
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala27
-rw-r--r--test/test/DeSugarTest.scala2
-rw-r--r--tests/neg/i1605.scala2
-rw-r--r--tests/pickling/annot.scala12
-rw-r--r--tests/pickling/pickleTypes.scala13
-rw-r--r--tests/pickling/simple.scala6
37 files changed, 703 insertions, 497 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/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala
index 03c4315fe..a7c449947 100644
--- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala
+++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala
@@ -973,7 +973,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
}
object This extends ThisDeconstructor {
- def get = field.qual
+ def get = field.qual.name
def apply(s: Symbol): This = tpd.This(s.asClass)
}
@@ -1020,7 +1020,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
}
object Super extends SuperDeconstructor {
def _1: Tree = field.qual
- def _2: Name = field.mix
+ def _2: Name = field.mix.name
}
object ArrayValue extends ArrayValueDeconstructor {
def _1: Type = field.tpe match {
diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala
index d568e3d31..366a0e225 100644
--- a/src/dotty/tools/dotc/ast/Desugar.scala
+++ b/src/dotty/tools/dotc/ast/Desugar.scala
@@ -234,7 +234,7 @@ object desugar {
if (tdef.mods is PrivateLocalParam) {
val tparam = cpy.TypeDef(tdef)(name = tdef.name.expandedName(ctx.owner))
.withMods(tdef.mods &~ PrivateLocal | ExpandedName)
- val alias = cpy.TypeDef(tdef)(rhs = refOfDef(tparam), tparams = Nil)
+ val alias = cpy.TypeDef(tdef)(rhs = refOfDef(tparam))
.withMods(tdef.mods & VarianceFlags | PrivateLocalParamAccessor | Synthetic)
Thicket(tparam, alias)
}
@@ -341,7 +341,7 @@ object desugar {
val isDefinedMeth = syntheticProperty(nme.isDefined, Literal(Constant(true)))
val caseParams = constrVparamss.head.toArray
val productElemMeths = for (i <- 0 until arity) yield
- syntheticProperty(nme.selectorName(i), Select(This(EmptyTypeName), caseParams(i).name))
+ syntheticProperty(nme.selectorName(i), Select(This(EmptyTypeIdent), caseParams(i).name))
def isRepeated(tree: Tree): Boolean = tree match {
case PostfixOp(_, nme.raw.STAR) => true
case ByNameTypeTree(tree1) => isRepeated(tree1)
@@ -463,8 +463,7 @@ object desugar {
cpy.TypeDef(cdef)(
name = className,
rhs = cpy.Template(impl)(constr, parents1, self1,
- tparamAccessors ::: vparamAccessors ::: normalizedBody ::: caseClassMeths),
- tparams = Nil)
+ tparamAccessors ::: vparamAccessors ::: normalizedBody ::: caseClassMeths))
}
// install the watch on classTycon
diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala
index 8b2915174..d1e6bd38a 100644
--- a/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -272,7 +272,12 @@ trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped]
case mdef: ValOrDefDef =>
mdef.unforcedRhs == EmptyTree && !mdef.name.isConstructorName && !mdef.mods.is(ParamAccessor)
case mdef: TypeDef =>
- mdef.rhs.isEmpty || mdef.rhs.isInstanceOf[TypeBoundsTree]
+ def isBounds(rhs: Tree): Boolean = rhs match {
+ case _: TypeBoundsTree => true
+ case PolyTypeTree(_, body) => isBounds(body)
+ case _ => false
+ }
+ mdef.rhs.isEmpty || isBounds(mdef.rhs)
case _ => false
}
@@ -382,9 +387,9 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
def isIdempotentRef(tree: Tree)(implicit ctx: Context) =
refPurity(tree) >= Idempotent
- /** If `tree` is a constant expression, its value as a Literal,
+ /** If `tree` is a constant expression, its value as a Literal,
* or `tree` itself otherwise.
- *
+ *
* Note: Demanding idempotency instead of purity in literalize is strictly speaking too loose.
* Example
*
@@ -410,11 +415,11 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
*
* Revisit this issue once we have implemented `inline`. Then we can demand
* purity of the prefix unless the selection goes to an inline val.
- *
+ *
* Note: This method should be applied to all term tree nodes that are not literals,
* that can be idempotent, and that can have constant types. So far, only nodes
- * of the following classes qualify:
- *
+ * of the following classes qualify:
+ *
* Ident
* Select
* TypeApply
diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala
index 9108a4d22..2801bcae2 100644
--- a/src/dotty/tools/dotc/ast/Trees.scala
+++ b/src/dotty/tools/dotc/ast/Trees.scala
@@ -60,18 +60,18 @@ object Trees {
with Cloneable {
if (Stats.enabled) ntrees += 1
-
+
private def nxId = {
nextId += 1
//assert(nextId != 199, this)
- nextId
+ nextId
}
/** A unique identifier for this tree. Used for debugging, and potentially
* tracking presentation compiler interactions
*/
private var myUniqueId: Int = nxId
-
+
def uniqueId = myUniqueId
/** The type constructor at the root of the tree */
@@ -159,7 +159,7 @@ object Trees {
/** Does this tree define a new symbol that is not defined elsewhere? */
def isDef: Boolean = false
- /** Is this tree either the empty tree or the empty ValDef? */
+ /** Is this tree either the empty tree or the empty ValDef or an empty type ident? */
def isEmpty: Boolean = false
/** Convert tree to a list. Gives a singleton list, except
@@ -192,7 +192,7 @@ object Trees {
override def hashCode(): Int = uniqueId // for debugging; was: System.identityHashCode(this)
override def equals(that: Any) = this eq that.asInstanceOf[AnyRef]
-
+
override def clone: Tree[T] = {
val tree = super.clone.asInstanceOf[Tree[T]]
tree.myUniqueId = nxId
@@ -353,7 +353,7 @@ object Trees {
}
/** qual.this */
- case class This[-T >: Untyped] private[ast] (qual: TypeName)
+ case class This[-T >: Untyped] private[ast] (qual: untpd.Ident)
extends DenotingTree[T] with TermTree[T] {
type ThisTree[-T >: Untyped] = This[T]
// Denotation of a This tree is always the underlying class; needs correction for modules.
@@ -368,7 +368,7 @@ object Trees {
}
/** C.super[mix], where qual = C.this */
- case class Super[-T >: Untyped] private[ast] (qual: Tree[T], mix: TypeName)
+ case class Super[-T >: Untyped] private[ast] (qual: Tree[T], mix: untpd.Ident)
extends ProxyTree[T] with TermTree[T] {
type ThisTree[-T >: Untyped] = Super[T]
def forwardTo = qual
@@ -653,12 +653,6 @@ object Trees {
/** Is this a definition of a class? */
def isClassDef = rhs.isInstanceOf[Template[_]]
-
- /** If this a non-class type definition, its type parameters.
- * Can be different from Nil only for PolyTypeDefs, which are always
- * untyped and get eliminated during desugaring.
- */
- def tparams: List[untpd.TypeDef] = Nil
}
/** extends parents { self => body } */
@@ -896,12 +890,12 @@ object Trees {
case tree: Select if (qualifier eq tree.qualifier) && (name == tree.name) => tree
case _ => finalize(tree, untpd.Select(qualifier, name))
}
- def This(tree: Tree)(qual: TypeName): This = tree match {
- case tree: This if qual == tree.qual => tree
+ def This(tree: Tree)(qual: untpd.Ident): This = tree match {
+ case tree: This if qual eq tree.qual => tree
case _ => finalize(tree, untpd.This(qual))
}
- def Super(tree: Tree)(qual: Tree, mix: TypeName): Super = tree match {
- case tree: Super if (qual eq tree.qual) && (mix == tree.mix) => tree
+ def Super(tree: Tree)(qual: Tree, mix: untpd.Ident): Super = tree match {
+ case tree: Super if (qual eq tree.qual) && (mix eq tree.mix) => tree
case _ => finalize(tree, untpd.Super(qual, mix))
}
def Apply(tree: Tree)(fun: Tree, args: List[Tree])(implicit ctx: Context): Apply = tree match {
@@ -1023,9 +1017,9 @@ object Trees {
case tree: DefDef if (name == tree.name) && (tparams eq tree.tparams) && (vparamss eq tree.vparamss) && (tpt eq tree.tpt) && (rhs eq tree.unforcedRhs) => tree
case _ => finalize(tree, untpd.DefDef(name, tparams, vparamss, tpt, rhs))
}
- def TypeDef(tree: Tree)(name: TypeName, rhs: Tree, tparams: List[untpd.TypeDef]): TypeDef = tree match {
- case tree: TypeDef if (name == tree.name) && (rhs eq tree.rhs) && (tparams eq tree.tparams) => tree
- case _ => finalize(tree, untpd.TypeDef(name, tparams, rhs))
+ def TypeDef(tree: Tree)(name: TypeName, rhs: Tree): TypeDef = tree match {
+ case tree: TypeDef if (name == tree.name) && (rhs eq tree.rhs) => tree
+ case _ => finalize(tree, untpd.TypeDef(name, rhs))
}
def Template(tree: Tree)(constr: DefDef, parents: List[Tree], self: ValDef, body: LazyTreeList): Template = tree match {
case tree: Template if (constr eq tree.constr) && (parents eq tree.parents) && (self eq tree.self) && (body eq tree.unforcedBody) => tree
@@ -1064,8 +1058,8 @@ object Trees {
ValDef(tree: Tree)(name, tpt, rhs)
def DefDef(tree: DefDef)(name: TermName = tree.name, tparams: List[TypeDef] = tree.tparams, vparamss: List[List[ValDef]] = tree.vparamss, tpt: Tree = tree.tpt, rhs: LazyTree = tree.unforcedRhs): DefDef =
DefDef(tree: Tree)(name, tparams, vparamss, tpt, rhs)
- def TypeDef(tree: TypeDef)(name: TypeName = tree.name, rhs: Tree = tree.rhs, tparams: List[untpd.TypeDef] = tree.tparams): TypeDef =
- TypeDef(tree: Tree)(name, rhs, tparams)
+ def TypeDef(tree: TypeDef)(name: TypeName = tree.name, rhs: Tree = tree.rhs): TypeDef =
+ TypeDef(tree: Tree)(name, rhs)
def Template(tree: Template)(constr: DefDef = tree.constr, parents: List[Tree] = tree.parents, self: ValDef = tree.self, body: LazyTreeList = tree.unforcedBody): Template =
Template(tree: Tree)(constr, parents, self, body)
}
@@ -1146,7 +1140,7 @@ object Trees {
case tree @ DefDef(name, tparams, vparamss, tpt, _) =>
cpy.DefDef(tree)(name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(tree.rhs))
case tree @ TypeDef(name, rhs) =>
- cpy.TypeDef(tree)(name, transform(rhs), tree.tparams)
+ cpy.TypeDef(tree)(name, transform(rhs))
case tree @ Template(constr, parents, self, _) =>
cpy.Template(tree)(transformSub(constr), transform(parents), transformSub(self), transformStats(tree.body))
case Import(expr, selectors) =>
@@ -1294,7 +1288,6 @@ object Trees {
case tree: Bind => cpy.Bind(tree)(newName, tree.body)
case tree: ValDef => cpy.ValDef(tree)(name = newName.asTermName)
case tree: DefDef => cpy.DefDef(tree)(name = newName.asTermName)
- case tree: untpd.PolyTypeDef => untpd.cpy.PolyTypeDef(tree)(newName.asTypeName, tree.tparams, tree.rhs).withMods(tree.rawMods)
case tree: TypeDef => cpy.TypeDef(tree)(name = newName.asTypeName)
}
}.asInstanceOf[tree.ThisTree[T]]
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index fc96735b0..44e1cf188 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -31,11 +31,14 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
untpd.Select(qualifier, tp.name).withType(tp)
def This(cls: ClassSymbol)(implicit ctx: Context): This =
- untpd.This(cls.name).withType(cls.thisType)
+ untpd.This(untpd.Ident(cls.name)).withType(cls.thisType)
- def Super(qual: Tree, mix: TypeName, inConstrCall: Boolean, mixinClass: Symbol = NoSymbol)(implicit ctx: Context): Super =
+ def Super(qual: Tree, mix: untpd.Ident, inConstrCall: Boolean, mixinClass: Symbol)(implicit ctx: Context): Super =
ta.assignType(untpd.Super(qual, mix), qual, inConstrCall, mixinClass)
+ def Super(qual: Tree, mixName: TypeName, inConstrCall: Boolean, mixinClass: Symbol = NoSymbol)(implicit ctx: Context): Super =
+ Super(qual, if (mixName.isEmpty) untpd.EmptyTypeIdent else untpd.Ident(mixName), inConstrCall, mixinClass)
+
def Apply(fn: Tree, args: List[Tree])(implicit ctx: Context): Apply =
ta.assignType(untpd.Apply(fn, args), fn, args)
@@ -133,7 +136,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 +145,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)
diff --git a/src/dotty/tools/dotc/ast/untpd.scala b/src/dotty/tools/dotc/ast/untpd.scala
index f259bdc57..6c5210287 100644
--- a/src/dotty/tools/dotc/ast/untpd.scala
+++ b/src/dotty/tools/dotc/ast/untpd.scala
@@ -80,8 +80,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree]) extends TypTree
case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) extends DefTree
- class PolyTypeDef(name: TypeName, override val tparams: List[TypeDef], rhs: Tree)
- extends TypeDef(name, rhs)
+ @sharable object EmptyTypeIdent extends Ident(tpnme.EMPTY) with WithoutTypeOrPos[Untyped] {
+ override def isEmpty = true
+ }
/** A block arising from a right-associative infix operation, where, e.g.
*
@@ -228,8 +229,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def BackquotedIdent(name: Name): BackquotedIdent = new BackquotedIdent(name)
def Select(qualifier: Tree, name: Name): Select = new Select(qualifier, name)
def SelectWithSig(qualifier: Tree, name: Name, sig: Signature): Select = new SelectWithSig(qualifier, name, sig)
- def This(qual: TypeName): This = new This(qual)
- def Super(qual: Tree, mix: TypeName): Super = new Super(qual, mix)
+ def This(qual: Ident): This = new This(qual)
+ def Super(qual: Tree, mix: Ident): Super = new Super(qual, mix)
def Apply(fun: Tree, args: List[Tree]): Apply = new Apply(fun, args)
def TypeApply(fun: Tree, args: List[Tree]): TypeApply = new TypeApply(fun, args)
def Literal(const: Constant): Literal = new Literal(const)
@@ -310,9 +311,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def TypeTree(tpe: Type)(implicit ctx: Context): TypedSplice = TypedSplice(TypeTree().withTypeUnchecked(tpe))
- def TypeDef(name: TypeName, tparams: List[TypeDef], rhs: Tree): TypeDef =
- if (tparams.isEmpty) TypeDef(name, rhs) else new PolyTypeDef(name, tparams, rhs)
-
def unitLiteral = Literal(Constant(()))
def ref(tp: NamedType)(implicit ctx: Context): Tree =
@@ -348,6 +346,9 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def makeSyntheticParameter(n: Int = 1, tpt: Tree = TypeTree())(implicit ctx: Context): ValDef =
ValDef(nme.syntheticParamName(n), tpt, EmptyTree).withFlags(SyntheticTermParam)
+ def lambdaAbstract(tparams: List[TypeDef], tpt: Tree)(implicit ctx: Context) =
+ if (tparams.isEmpty) tpt else PolyTypeTree(tparams, tpt)
+
/** A reference to given definition. If definition is a repeated
* parameter, the reference will be a repeated argument.
*/
@@ -392,10 +393,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
if (expr eq tree.expr) && (handler eq tree.handler) && (finalizer eq tree.finalizer) => tree
case _ => untpd.ParsedTry(expr, handler, finalizer).withPos(tree.pos)
}
- def PolyTypeDef(tree: Tree)(name: TypeName, tparams: List[TypeDef], rhs: Tree) = tree match {
- case tree: PolyTypeDef if (name eq tree.name) && (tparams eq tree.tparams) && (rhs eq tree.rhs) => tree
- case _ => new PolyTypeDef(name, tparams, rhs).withPos(tree.pos)
- }
def SymbolLit(tree: Tree)(str: String) = tree match {
case tree: SymbolLit if str == tree.str => tree
case _ => untpd.SymbolLit(str).withPos(tree.pos)
@@ -506,8 +503,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
cpy.ContextBounds(tree)(transformSub(bounds), transform(cxBounds))
case PatDef(mods, pats, tpt, rhs) =>
cpy.PatDef(tree)(mods, transform(pats), transform(tpt), transform(rhs))
- case tree: PolyTypeDef =>
- cpy.PolyTypeDef(tree)(tree.name, transformSub(tree.tparams), transform(tree.rhs))
case _ =>
super.transform(tree)
}
@@ -553,8 +548,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
this(this(x, bounds), cxBounds)
case PatDef(mods, pats, tpt, rhs) =>
this(this(this(x, pats), tpt), rhs)
- case tree: PolyTypeDef =>
- this(this(x, tree.tparams), tree.rhs)
case TypedSplice(tree) =>
this(x, tree)
case _ =>
@@ -566,10 +559,4 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
class UntypedDeepFolder[X](f: (X, Tree) => X) extends UntypedTreeAccumulator[X] {
def apply(x: X, tree: Tree)(implicit ctx: Context): X = foldOver(f(x, tree), tree)
}
-
- override def rename(tree: NameTree, newName: Name)(implicit ctx: Context): tree.ThisTree[Untyped] = tree match {
- case t: PolyTypeDef =>
- cpy.PolyTypeDef(t)(newName.asTypeName, t.tparams, t.rhs).asInstanceOf[tree.ThisTree[Untyped]]
- case _ => super.rename(tree, newName)
- }
}
diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala
index 920c9635e..c2a14b36f 100644
--- a/src/dotty/tools/dotc/core/StdNames.scala
+++ b/src/dotty/tools/dotc/core/StdNames.scala
@@ -735,15 +735,11 @@ object StdNames {
class ScalaTypeNames extends ScalaNames[TypeName] {
protected implicit def fromString(s: String): TypeName = typeName(s)
- def syntheticTypeParamName(i: Int): TypeName = "T" + i
- def syntheticLambdaParamName(i: Int): TypeName = "X" + i
+ def syntheticTypeParamName(i: Int): TypeName = "X" + i
def syntheticTypeParamNames(num: Int): List[TypeName] =
(0 until num).map(syntheticTypeParamName)(breakOut)
- def syntheticLambdaParamNames(num: Int): List[TypeName] =
- (0 until num).map(syntheticLambdaParamName)(breakOut)
-
final val Conforms = encode("<:<")
final val Uninstantiated: TypeName = "?$"
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index 8aaf77032..70819e590 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -340,10 +340,11 @@ class TypeApplications(val self: Type) extends AnyVal {
def LambdaAbstract(tparams: List[TypeParamInfo])(implicit ctx: Context): Type = {
def expand(tp: Type) =
PolyType(
- tpnme.syntheticLambdaParamNames(tparams.length), tparams.map(_.paramVariance))(
+ tparams.map(_.paramName), tparams.map(_.paramVariance))(
tl => tparams.map(tparam => tl.lifted(tparams, tparam.paramBounds).bounds),
tl => tl.lifted(tparams, tp))
- self match {
+ if (tparams.isEmpty) self
+ else self match {
case self: TypeAlias =>
self.derivedTypeAlias(expand(self.alias))
case self @ TypeBounds(lo, hi) =>
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 0e1d373a8..f78820fff 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -1267,7 +1267,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
original(tp1.appliedTo(tp1.typeParams.map(_.paramBoundsAsSeenFrom(tp1))), tp2)
else
PolyType(
- paramNames = tpnme.syntheticLambdaParamNames(tparams1.length),
+ paramNames = tpnme.syntheticTypeParamNames(tparams1.length),
variances = (tparams1, tparams2).zipped.map((tparam1, tparam2) =>
(tparam1.paramVariance + tparam2.paramVariance) / 2))(
paramBoundsExp = tl => (tparams1, tparams2).zipped.map((tparam1, tparam2) =>
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index ae248295c..89bc21929 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -2526,7 +2526,7 @@ object Types {
case _: MethodType => true
case _ => false
}
-
+
/** Is this polytype a higher-kinded type lambda as opposed to a polymorphic?
* method type? Only type lambdas get created with variances, that's how we can tell.
*/
@@ -2621,17 +2621,11 @@ object Types {
unique(new PolyType(paramNames, vs)(paramBoundsExp, resultTypeExp))
}
- def fromSymbols(tparams: List[Symbol], resultType: Type)(implicit ctx: Context): Type =
- if (tparams.isEmpty) resultType
- else apply(tparams map (_.name.asTypeName), tparams.map(_.variance))(
- pt => tparams.map(tparam => pt.lifted(tparams, tparam.info).bounds),
- pt => pt.lifted(tparams, resultType))
-
def unapply(tl: PolyType): Some[(List[LambdaParam], Type)] =
Some((tl.typeParams, tl.resType))
def any(n: Int)(implicit ctx: Context) =
- apply(tpnme.syntheticLambdaParamNames(n), List.fill(n)(0))(
+ apply(tpnme.syntheticTypeParamNames(n), List.fill(n)(0))(
pt => List.fill(n)(TypeBounds.empty), pt => defn.AnyType)
}
diff --git a/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala b/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
index 1570dbca0..97a82e80d 100644
--- a/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
+++ b/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala
@@ -217,7 +217,7 @@ class ClassfileParser(
if (isEnum) denot.info = ConstantType(Constant(sym))
if (isConstructor) stripOuterParamFromConstructor()
setPrivateWithin(denot, jflags)
- denot.info = depoly(parseAttributes(sym, denot.info), denot)
+ denot.info = translateTempPoly(parseAttributes(sym, denot.info))
if (isConstructor) normalizeConstructorInfo()
if ((denot is Flags.Method) && (jflags & JAVA_ACC_VARARGS) != 0)
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..cb1b56c3c 100644
--- a/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
+++ b/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
@@ -71,10 +71,11 @@ 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
+ QUALTHIS typeIdent_Tree
NEW cls_Type
- SUPER Length this_Term mixinTrait_Type?
+ SUPER Length this_Term mixinTypeIdent_Tree?
TYPED Length expr_Term ascription_Type
NAMEDARG Length paramName_NameRef arg_Term
ASSIGN Length lhs_Term rhs_Term
@@ -89,6 +90,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 for all type idents
+ SELECTtpt NameRef qual_Term
+ SINGLETONtpt Path
+ REFINEDtpt 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 +145,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
@@ -268,22 +280,27 @@ object TastyFormat {
final val RENAMED = 79
final val THIS = 96
- 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 QUALTHIS = 97
+ final val CLASSconst = 98
+ final val ENUMconst = 99
+ final val BYNAMEtype = 100
+ final val BYNAMEtpt = 101
+ final val NEW = 102
+ final val IMPLICITarg = 103
+ final val PRIVATEqualified = 104
+ final val PROTECTEDqualified = 105
+ final val RECtype = 106
+ final val SINGLETONtpt = 107
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 +310,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 +389,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 +466,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,24 +501,34 @@ 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"
case SELFDEF => "SELFDEF"
case THIS => "THIS"
+ case QUALTHIS => "QUALTHIS"
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..c844d522e 100644
--- a/src/dotty/tools/dotc/core/tasty/TastyPickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/TastyPickler.scala
@@ -54,14 +54,11 @@ class TastyPickler {
all.bytes
}
- /**
- * Addresses in TASTY file of trees, stored by pickling.
- * Note that trees are checked for reference equality,
- * so one can reliably use this function only directly after `pickler`.
- * 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.
+ /** The address in the TASTY file of a given tree, or None if unknown.
+ * Note that trees are looked up by reference equality,
+ * so one can reliably use this function only directly after `pickler`.
*/
- 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..6c7982d78 100644
--- a/src/dotty/tools/dotc/core/tasty/TreeBuffer.scala
+++ b/src/dotty/tools/dotc/core/tasty/TreeBuffer.scala
@@ -17,26 +17,17 @@ 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 at which a tree is pickled. */
+ private val treeAddrs = new java.util.IdentityHashMap[Tree, Any] // really: Addr | Null
- /** 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]
+ def registerTreeAddr(tree: Tree): Addr = treeAddrs.get(tree) match {
+ case null => treeAddrs.put(tree, currentAddr); currentAddr
+ case addr: Addr => addr
+ }
- 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 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 9dfb78798..80270aa25 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._
@@ -49,10 +50,6 @@ class TreePickler(pickler: TastyPickler) {
case None =>
}
}
-
- def rhs(tdef: TypeDef)(implicit ctx: Context) =
- if (tdef.symbol.isClass) tdef.rhs
- else TypeTree(tdef.symbol.info).withPos(tdef.rhs.pos)
private def pickleName(name: Name): Unit = writeNat(nameIndex(name).index)
private def pickleName(name: TastyName): Unit = writeNat(nameIndex(name).index)
@@ -157,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)
@@ -253,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)
@@ -310,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)
@@ -336,7 +328,7 @@ class TreePickler(pickler: TastyPickler) {
tree match {
case tree: ValDef => pickleDef(PARAM, tree.symbol, tree.tpt)
case tree: DefDef => pickleDef(PARAM, tree.symbol, tree.tpt, tree.rhs)
- case tree: TypeDef => pickleDef(TYPEPARAM, tree.symbol, rhs(tree))
+ case tree: TypeDef => pickleDef(TYPEPARAM, tree.symbol, tree.rhs)
}
}
@@ -350,181 +342,231 @@ 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(qual) =>
+ if (qual.isEmpty) pickleType(tree.tpe)
+ else {
+ writeByte(QUALTHIS)
+ val ThisType(tref) = tree.tpe
+ pickleTree(qual.withType(tref))
}
- }
- 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)
+ 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
}
- 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) }
+ 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)
}
- }
- pickleDef(DEFDEF, tree.symbol, tree.tpt, tree.rhs, pickleAllParams)
- case tree: TypeDef =>
- pickleDef(TYPEDEF, tree.symbol, rhs(tree))
- 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 TypeApply(fun, args) =>
+ writeByte(TYPEAPPLY)
+ withLength {
+ pickleTree(fun)
+ args.foreach(pickleTpt)
+ }
+ 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: TypeRef) = tree.tpe
+ pickleTree(mix.withType(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 d2605afea..eba9ab533 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()
@@ -696,7 +702,10 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
TypeDef(readTemplate(localCtx))
} else {
val rhs = readTpt()
- sym.info = rhs.tpe
+ sym.info = rhs.tpe match {
+ case _: TypeBounds | _: ClassInfo => rhs.tpe
+ case _ => TypeAlias(rhs.tpe, sym.variance)
+ }
TypeDef(rhs)
}
case PARAM =>
@@ -846,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")
@@ -856,34 +870,52 @@ 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 readQualId(): (untpd.Ident, TypeRef) = {
+ val qual = readTerm().asInstanceOf[untpd.Ident]
+ (untpd.Ident(qual.name).withPos(qual.pos), qual.tpe.asInstanceOf[TypeRef])
+ }
+
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 QUALTHIS =>
+ val (qual, tref) = readQualId()
+ untpd.This(qual).withType(ThisType.raw(tref))
case NEW =>
New(readTpt())
+ case SINGLETONtpt =>
+ SingletonTypeTree(readTerm())
+ case BYNAMEtpt =>
+ ByNameTypeTree(readTpt())
case _ =>
readPathTerm()
}
@@ -891,10 +923,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)
@@ -904,9 +941,8 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
(tag: @switch) match {
case SUPER =>
val qual = readTerm()
- val mixClass = ifBefore(end)(readType().typeSymbol, NoSymbol)
- val mixName = if (mixClass.exists) mixClass.name.asTypeName else tpnme.EMPTY
- tpd.Super(qual, mixName, ctx.mode.is(Mode.InSuperCall), mixClass)
+ val (mixId, mixTpe) = ifBefore(end)(readQualId(), (untpd.EmptyTypeIdent, NoType))
+ tpd.Super(qual, mixId, ctx.mode.is(Mode.InSuperCall), mixTpe.typeSymbol)
case APPLY =>
val fn = readTerm()
val isJava = fn.symbol.is(JavaDefined)
@@ -934,7 +970,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())
@@ -971,6 +1007,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()
}
@@ -983,11 +1041,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/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
index 70148b3e2..b01f6cc6a 100644
--- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
+++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala
@@ -40,29 +40,15 @@ object Scala2Unpickler {
/** Temporary type for classinfos, will be decomposed on completion of the class */
case class TempClassInfoType(parentTypes: List[Type], decls: Scope, clazz: Symbol) extends UncachedGroundType
- /** Convert temp poly type to some native Dotty idiom.
- * @param denot The denotation that gets the converted type as info.
- * If `denot` is not an abstract type, this simply returns an equivalent `PolyType`.
- * If `denot` is an abstract type, it converts a
- *
- * TempPolyType(List(v_1 T_1, ..., v_n T_n), lo .. hi)
- *
- * to a type lambda using `parameterizeWith/LambdaAbstract`.
- */
- def depoly(tp: Type, denot: SymDenotation)(implicit ctx: Context): Type = tp match {
- case TempPolyType(tparams, restpe) =>
- if (denot.isType) {
- assert(!denot.isClass)
- restpe.LambdaAbstract(tparams)
- }
- else
- PolyType.fromSymbols(tparams, restpe)
+ /** Convert temp poly type to poly type and leave other types alone. */
+ def translateTempPoly(tp: Type)(implicit ctx: Context): Type = tp match {
+ case TempPolyType(tparams, restpe) => restpe.LambdaAbstract(tparams)
case tp => tp
}
def addConstructorTypeParams(denot: SymDenotation)(implicit ctx: Context) = {
assert(denot.isConstructor)
- denot.info = PolyType.fromSymbols(denot.owner.typeParams, denot.info)
+ denot.info = denot.info.LambdaAbstract(denot.owner.typeParams)
}
/** Convert array parameters denoting a repeated parameter of a Java method
@@ -549,7 +535,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas
val selfInfo = if (atEnd) NoType else readTypeRef()
setClassInfo(denot, tp, selfInfo)
case denot =>
- val tp1 = depoly(tp, denot)
+ val tp1 = translateTempPoly(tp)
denot.info =
if (tag == ALIASsym) TypeAlias(tp1)
else if (denot.isType) checkNonCyclic(denot.symbol, tp1, reportErrors = false)
diff --git a/src/dotty/tools/dotc/parsing/JavaParsers.scala b/src/dotty/tools/dotc/parsing/JavaParsers.scala
index b6a423dc7..0f63b25bb 100644
--- a/src/dotty/tools/dotc/parsing/JavaParsers.scala
+++ b/src/dotty/tools/dotc/parsing/JavaParsers.scala
@@ -417,7 +417,7 @@ object JavaParsers {
atPos(in.offset) {
val name = identForType()
val hi = if (in.token == EXTENDS) { in.nextToken() ; bound() } else EmptyTree
- TypeDef(name, Nil, TypeBoundsTree(EmptyTree, hi)).withMods(Modifiers(flags))
+ TypeDef(name, TypeBoundsTree(EmptyTree, hi)).withMods(Modifiers(flags))
}
def bound(): Tree =
@@ -625,8 +625,7 @@ object JavaParsers {
val template = cdef.rhs.asInstanceOf[Template]
cpy.TypeDef(cdef)(cdef.name,
cpy.Template(template)(template.constr, template.parents, template.self,
- importCompanionObject(cdef) :: template.body),
- cdef.tparams).withMods(cdef.mods)
+ importCompanionObject(cdef) :: template.body)).withMods(cdef.mods)
}
List(makeCompanionObject(cdefNew, statics), cdefNew)
@@ -715,7 +714,7 @@ object JavaParsers {
val (statics, body) = typeBody(INTERFACE, name, tparams)
val iface = atPos(start, nameOffset) {
TypeDef(
- name, tparams,
+ name,
makeTemplate(parents, body, tparams, false)).withMods(mods | Flags.Trait | Flags.JavaInterface | Flags.Abstract)
}
addCompanionObject(statics, iface)
@@ -830,7 +829,7 @@ object JavaParsers {
Select(New(javaLangDot(tpnme.Enum)), nme.CONSTRUCTOR), List(enumType)),
List(Literal(Constant(null)),Literal(Constant(0))))
val enum = atPos(start, nameOffset) {
- TypeDef(name, List(),
+ TypeDef(name,
makeTemplate(superclazz :: interfaces, body, List(), true)).withMods(mods | Flags.Enum)
}
addCompanionObject(consts ::: statics ::: predefs, enum)
diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala
index bb76de6cc..fa0576c7a 100644
--- a/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -527,27 +527,28 @@ object Parsers {
*/
def path(thisOK: Boolean, finish: Tree => Tree = id): Tree = {
val start = in.offset
- def handleThis(name: TypeName) = {
+ def handleThis(qual: Ident) = {
in.nextToken()
- val t = atPos(start) { This(name) }
+ val t = atPos(start) { This(qual) }
if (!thisOK && in.token != DOT) syntaxError("`.' expected")
dotSelectors(t, finish)
}
- def handleSuper(name: TypeName) = {
+ def handleSuper(qual: Ident) = {
in.nextToken()
val mix = mixinQualifierOpt()
- val t = atPos(start) { Super(This(name), mix) }
+ val t = atPos(start) { Super(This(qual), mix) }
accept(DOT)
dotSelectors(selector(t), finish)
}
- if (in.token == THIS) handleThis(tpnme.EMPTY)
- else if (in.token == SUPER) handleSuper(tpnme.EMPTY)
+ if (in.token == THIS) handleThis(EmptyTypeIdent)
+ else if (in.token == SUPER) handleSuper(EmptyTypeIdent)
else {
val t = termIdent()
if (in.token == DOT) {
+ def qual = cpy.Ident(t)(t.name.toTypeName)
in.nextToken()
- if (in.token == THIS) handleThis(t.name.toTypeName)
- else if (in.token == SUPER) handleSuper(t.name.toTypeName)
+ if (in.token == THIS) handleThis(qual)
+ else if (in.token == SUPER) handleSuper(qual)
else selectors(t, finish)
}
else t
@@ -556,9 +557,9 @@ object Parsers {
/** MixinQualifier ::= `[' Id `]'
*/
- def mixinQualifierOpt(): TypeName =
- if (in.token == LBRACKET) inBrackets(ident().toTypeName)
- else tpnme.EMPTY
+ def mixinQualifierOpt(): Ident =
+ if (in.token == LBRACKET) inBrackets(atPos(in.offset) { typeIdent() })
+ else EmptyTypeIdent
/** StableId ::= Id
* | Path `.' Id
@@ -617,7 +618,7 @@ object Parsers {
termIdent()
else if (in.token == THIS) {
in.nextToken()
- This(tpnme.EMPTY)
+ This(EmptyTypeIdent)
}
else if (in.token == LBRACE)
if (inPattern) Block(Nil, inBraces(pattern()))
@@ -1646,7 +1647,7 @@ object Parsers {
val bounds =
if (isConcreteOwner) typeParamBounds(name)
else typeBounds()
- TypeDef(name, hkparams, bounds).withMods(mods)
+ TypeDef(name, lambdaAbstract(hkparams, bounds)).withMods(mods)
}
}
commaSeparated(typeParam)
@@ -1956,9 +1957,9 @@ object Parsers {
in.token match {
case EQUALS =>
in.nextToken()
- TypeDef(name, tparams, typ()).withMods(mods).setComment(docstring)
+ TypeDef(name, lambdaAbstract(tparams, typ())).withMods(mods).setComment(docstring)
case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | NEWLINES | COMMA | RBRACE | EOF =>
- TypeDef(name, tparams, typeBounds()).withMods(mods).setComment(docstring)
+ TypeDef(name, lambdaAbstract(tparams, typeBounds())).withMods(mods).setComment(docstring)
case _ =>
syntaxErrorOrIncomplete("`=', `>:', or `<:' expected")
EmptyTree
@@ -2145,7 +2146,7 @@ object Parsers {
val first = expr1()
if (in.token == ARROW) {
first match {
- case Typed(tree @ This(tpnme.EMPTY), tpt) =>
+ case Typed(tree @ This(EmptyTypeIdent), tpt) =>
self = makeSelfDef(nme.WILDCARD, tpt).withPos(first.pos)
case _ =>
val ValDef(name, tpt, _) = convertToParam(first, expected = "self type clause")
diff --git a/src/dotty/tools/dotc/printing/PlainPrinter.scala b/src/dotty/tools/dotc/printing/PlainPrinter.scala
index 785f57897..4894fa019 100644
--- a/src/dotty/tools/dotc/printing/PlainPrinter.scala
+++ b/src/dotty/tools/dotc/printing/PlainPrinter.scala
@@ -127,7 +127,10 @@ class PlainPrinter(_ctx: Context) extends Printer {
homogenize(tp) match {
case tp: TypeType =>
toTextRHS(tp)
- case tp: TermRef if !tp.denotationIsCurrent || tp.symbol.is(Module) || tp.symbol.name.isImportName =>
+ case tp: TermRef
+ if !tp.denotationIsCurrent && !homogenizedView || // always print underyling when testing picklers
+ tp.symbol.is(Module) ||
+ tp.symbol.name.isImportName =>
toTextRef(tp) ~ ".type"
case tp: TermRef if tp.denot.isOverloaded =>
"<overloaded " ~ toTextRef(tp) ~ ">"
@@ -231,9 +234,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 7aaf2e190..29e1d4869 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,12 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
return toTextParents(tp.parentsWithArgs) ~ "{...}"
case JavaArrayType(elemtp) =>
return toText(elemtp) ~ "[]"
+ case tp: AnnotatedType if homogenizedView =>
+ // Positions of annotations in types are not serialized
+ // (they don't need to because we keep the original type tree with
+ // the original annotation anyway. Therefore, there will always be
+ // one version of the annotation tree that has the correct positions).
+ withoutPos(super.toText(tp))
case tp: SelectionProto =>
return "?{ " ~ toText(tp.name) ~ (" " provided !tp.name.decode.last.isLetterOrDigit) ~
": " ~ toText(tp.memberProto) ~ " }"
@@ -249,7 +268,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 +304,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 +358,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) =>
@@ -351,7 +372,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
case SeqLiteral(elems, elemtpt) =>
"[" ~ toTextGlobal(elems, ",") ~ " : " ~ toText(elemtpt) ~ "]"
case tree @ Inlined(call, bindings, body) =>
- (("/* inlined from " ~ toText(call) ~ "*/ ") provided !homogenizedView) ~
+ (("/* inlined from " ~ toText(call) ~ "*/ ") provided !homogenizedView) ~
blockText(bindings :+ body)
case tpt: untpd.DerivedTypeTree =>
"<derived typetree watching " ~ summarized(toText(tpt.watched)) ~ ">"
@@ -402,24 +423,27 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}
}
case tree @ TypeDef(name, rhs) =>
- def typeDefText(rhsText: Text) =
+ def typeDefText(tparamsText: => Text, rhsText: => Text) =
dclTextOr {
modText(tree.mods, "type") ~~ (varianceText(tree.mods) ~ nameIdText(tree)) ~
withEnclosingDef(tree) {
- val rhsText1 = if (tree.hasType) toText(tree.symbol.info) else rhsText
- tparamsText(tree.tparams) ~ rhsText1
+ if (tree.hasType) toText(tree.symbol.info) // TODO: always print RHS, once we pickle/unpickle type trees
+ else tparamsText ~ rhsText
}
}
- rhs match {
+ def recur(rhs: Tree, tparamsTxt: => Text): Text = rhs match {
case impl: Template =>
modText(tree.mods, if ((tree).mods is Trait) "trait" else "class") ~~
nameIdText(tree) ~ withEnclosingDef(tree) { toTextTemplate(impl) } ~
(if (tree.hasType && ctx.settings.verbose.value) i"[decls = ${tree.symbol.info.decls}]" else "")
case rhs: TypeBoundsTree =>
- typeDefText(toText(rhs))
- case _ =>
- typeDefText(optText(rhs)(" = " ~ _))
+ typeDefText(tparamsTxt, toText(rhs))
+ case PolyTypeTree(tparams, body) =>
+ recur(body, tparamsText(tparams))
+ case rhs =>
+ typeDefText(tparamsTxt, optText(rhs)(" = " ~ _))
}
+ recur(rhs, "")
case Import(expr, selectors) =>
def selectorText(sel: Tree): Text = sel match {
case Thicket(l :: r :: Nil) => toTextGlobal(l) ~ " => " ~ toTextGlobal(r)
@@ -516,22 +540,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[_]]) {
- val pos =
- if (homogenizedView && !tree.isInstanceOf[MemberDef]) tree.pos.toSynthetic
+ 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/Erasure.scala b/src/dotty/tools/dotc/transform/Erasure.scala
index a503d55e5..069176111 100644
--- a/src/dotty/tools/dotc/transform/Erasure.scala
+++ b/src/dotty/tools/dotc/transform/Erasure.scala
@@ -352,10 +352,10 @@ object Erasure extends TypeTestsCasts{
assignType(untpd.cpy.Select(tree)(qual, tree.name.primitiveArrayOp), qual)
def adaptIfSuper(qual: Tree): Tree = qual match {
- case Super(thisQual, tpnme.EMPTY) =>
+ case Super(thisQual, untpd.EmptyTypeIdent) =>
val SuperType(thisType, supType) = qual.tpe
if (sym.owner is Flags.Trait)
- cpy.Super(qual)(thisQual, sym.owner.asClass.name)
+ cpy.Super(qual)(thisQual, untpd.Ident(sym.owner.asClass.name))
.withType(SuperType(thisType, sym.owner.typeRef))
else
qual.withType(SuperType(thisType, thisType.firstParent))
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/src/dotty/tools/dotc/transform/SuperAccessors.scala b/src/dotty/tools/dotc/transform/SuperAccessors.scala
index 10be6db65..fea478c9b 100644
--- a/src/dotty/tools/dotc/transform/SuperAccessors.scala
+++ b/src/dotty/tools/dotc/transform/SuperAccessors.scala
@@ -106,7 +106,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
ctx.error(s"super not allowed here: use this.${sel.name.decode} instead", sel.pos)
else if (sym is Deferred) {
val member = sym.overridingSymbol(clazz)
- if (mix != tpnme.EMPTY ||
+ if (!mix.name.isEmpty ||
!member.exists ||
!((member is AbsOverride) && member.isIncompleteIn(clazz)))
ctx.error(
@@ -114,7 +114,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
sel.pos)
else ctx.log(i"ok super $sel ${sym.showLocated} $member $clazz ${member.isIncompleteIn(clazz)}")
}
- else if (mix == tpnme.EMPTY && !(sym.owner is Trait))
+ else if (mix.name.isEmpty && !(sym.owner is Trait))
// SI-4989 Check if an intermediate class between `clazz` and `sym.owner` redeclares the method as abstract.
for (intermediateClass <- clazz.info.baseClasses.tail.takeWhile(_ != sym.owner)) {
val overriding = sym.overridingSymbol(intermediateClass)
@@ -124,7 +124,7 @@ class SuperAccessors(thisTransformer: DenotTransformer) {
sel.pos)
}
- if (name.isTermName && mix == tpnme.EMPTY &&
+ if (name.isTermName && mix.name.isEmpty &&
((clazz is Trait) || clazz != ctx.owner.enclosingClass || !validCurrentClass))
superAccessorCall(sel)(ctx.withPhase(thisTransformer.next))
else sel
diff --git a/src/dotty/tools/dotc/transform/TreeTransform.scala b/src/dotty/tools/dotc/transform/TreeTransform.scala
index a1ccf0e63..5385ca720 100644
--- a/src/dotty/tools/dotc/transform/TreeTransform.scala
+++ b/src/dotty/tools/dotc/transform/TreeTransform.scala
@@ -977,7 +977,7 @@ object TreeTransforms {
if (mutatedInfo eq null) tree
else {
val rhs = transform(tree.rhs, mutatedInfo, cur)(localContext(tree.symbol))
- goTypeDef(cpy.TypeDef(tree)(tree.name, rhs, tree.tparams), mutatedInfo.nx.nxTransTypeDef(cur))
+ goTypeDef(cpy.TypeDef(tree)(tree.name, rhs), mutatedInfo.nx.nxTransTypeDef(cur))
}
case _ =>
tree
diff --git a/src/dotty/tools/dotc/typer/Inliner.scala b/src/dotty/tools/dotc/typer/Inliner.scala
index 6499167ad..3931fcaf4 100644
--- a/src/dotty/tools/dotc/typer/Inliner.scala
+++ b/src/dotty/tools/dotc/typer/Inliner.scala
@@ -120,7 +120,7 @@ object Inliner {
// Abstract accessed type over local refs
def abstractQualType(mtpe: Type): Type =
if (localRefs.isEmpty) mtpe
- else PolyType.fromSymbols(localRefs.map(_.symbol), mtpe).asInstanceOf[PolyType].flatten
+ else mtpe.LambdaAbstract(localRefs.map(_.symbol)).asInstanceOf[PolyType].flatten
val accessorType = abstractQualType(addQualType(dealiasMap(accessedType)))
val accessor = accessorSymbol(tree, accessorType).asTerm
@@ -290,8 +290,20 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
*/
private val paramProxy = new mutable.HashMap[Type, Type]
- /** A map from (direct and outer) this references in `rhs` to references of their proxies */
- private val thisProxy = new mutable.HashMap[Type, TermRef]
+ /** A map from the classes of (direct and outer) this references in `rhs`
+ * to references of their proxies.
+ * Note that we can't index by the ThisType itself since there are several
+ * possible forms to express what is logicaly the same ThisType. E.g.
+ *
+ * ThisType(TypeRef(ThisType(p), cls))
+ *
+ * vs
+ *
+ * ThisType(TypeRef(TermRef(ThisType(<root>), p), cls))
+ *
+ * These are different (wrt ==) types but represent logically the same key
+ */
+ private val thisProxy = new mutable.HashMap[ClassSymbol, TermRef]
/** A buffer for bindings that define proxies for actual arguments */
val bindingsBuf = new mutable.ListBuffer[ValOrDefDef]
@@ -349,13 +361,13 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
private def registerType(tpe: Type): Unit = tpe match {
case tpe: ThisType
if !ctx.owner.isContainedIn(tpe.cls) && !tpe.cls.is(Package) &&
- !thisProxy.contains(tpe) =>
+ !thisProxy.contains(tpe.cls) =>
if (tpe.cls.isStaticOwner)
- thisProxy(tpe) = tpe.cls.sourceModule.termRef
+ thisProxy(tpe.cls) = tpe.cls.sourceModule.termRef
else {
val proxyName = s"${tpe.cls.name}_this".toTermName
val proxyType = tpe.asSeenFrom(prefix.tpe, meth.owner)
- thisProxy(tpe) = newSym(proxyName, EmptyFlags, proxyType).termRef
+ thisProxy(tpe.cls) = newSym(proxyName, EmptyFlags, proxyType).termRef
registerType(meth.owner.thisType) // make sure we have a base from which to outer-select
}
case tpe: NamedType
@@ -408,7 +420,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
// and parameters to type references of their arguments or proxies.
val typeMap = new TypeMap {
def apply(t: Type) = t match {
- case t: ThisType => thisProxy.getOrElse(t, t)
+ case t: ThisType => thisProxy.getOrElse(t.cls, t)
case t: TypeRef => paramProxy.getOrElse(t, mapOver(t))
case t: SingletonType => paramProxy.getOrElse(t, mapOver(t))
case t => mapOver(t)
@@ -420,9 +432,13 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
def treeMap(tree: Tree) = {
tree match {
case _: This =>
- thisProxy.get(tree.tpe) match {
- case Some(t) => ref(t).withPos(tree.pos)
- case None => tree
+ tree.tpe match {
+ case thistpe: ThisType =>
+ thisProxy.get(thistpe.cls) match {
+ case Some(t) => ref(t).withPos(tree.pos)
+ case None => tree
+ }
+ case _ => tree
}
case _: Ident =>
paramProxy.get(tree.tpe) match {
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 78f0da1f0..148cf1da7 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -114,7 +114,7 @@ trait NamerContextOps { this: Context =>
if (param.info.isDirectRef(defn.ObjectClass)) param.info = defn.AnyType
make.fromSymbols(params, resultType)
}
- if (typeParams.nonEmpty) PolyType.fromSymbols(typeParams, monotpe)
+ if (typeParams.nonEmpty) monotpe.LambdaAbstract(typeParams)
else if (valueParamss.isEmpty) ExprType(monotpe)
else monotpe
}
@@ -294,7 +294,7 @@ class Namer { typer: Typer =>
val inSuperCall1 = if (tree.mods is ParamOrAccessor) EmptyFlags else inSuperCall
// suppress inSuperCall for constructor parameters
val higherKinded = tree match {
- case tree: TypeDef if tree.tparams.nonEmpty && isDeferred => HigherKinded
+ case TypeDef(_, PolyTypeTree(_, _)) if isDeferred => HigherKinded
case _ => EmptyFlags
}
@@ -616,8 +616,12 @@ class Namer { typer: Typer =>
nestedCtx = localContext(sym).setNewScope
myTypeParams = {
implicit val ctx: Context = nestedCtx
- completeParams(original.tparams)
- original.tparams.map(symbolOfTree(_).asType)
+ val tparams = original.rhs match {
+ case PolyTypeTree(tparams, _) => tparams
+ case _ => Nil
+ }
+ completeParams(tparams)
+ tparams.map(symbolOfTree(_).asType)
}
}
myTypeParams
@@ -1025,7 +1029,11 @@ class Namer { typer: Typer =>
// inspects a TypeRef's info, instead of simply dealiasing alias types.
val isDerived = tdef.rhs.isInstanceOf[untpd.DerivedTypeTree]
- val rhsBodyType = typedAheadType(tdef.rhs).tpe
+ val rhs = tdef.rhs match {
+ case PolyTypeTree(_, body) => body
+ case rhs => rhs
+ }
+ val rhsBodyType = typedAheadType(rhs).tpe
val rhsType = if (isDerived) rhsBodyType else abstracted(rhsBodyType)
val unsafeInfo = rhsType match {
case bounds: TypeBounds => bounds
diff --git a/src/dotty/tools/dotc/typer/TypeAssigner.scala b/src/dotty/tools/dotc/typer/TypeAssigner.scala
index b1fed308c..ee2d68278 100644
--- a/src/dotty/tools/dotc/typer/TypeAssigner.scala
+++ b/src/dotty/tools/dotc/typer/TypeAssigner.scala
@@ -282,7 +282,7 @@ trait TypeAssigner {
}
def assignType(tree: untpd.This)(implicit ctx: Context) = {
- val cls = qualifyingClass(tree, tree.qual, packageOK = false)
+ val cls = qualifyingClass(tree, tree.qual.name, packageOK = false)
tree.withType(cls.thisType)
}
@@ -291,7 +291,7 @@ trait TypeAssigner {
val qtype @ ThisType(_) = qual.tpe
val cls = qtype.cls
- def findMixinSuper(site: Type): Type = site.parents filter (_.name == mix) match {
+ def findMixinSuper(site: Type): Type = site.parents filter (_.name == mix.name) match {
case p :: Nil =>
p
case Nil =>
@@ -431,7 +431,18 @@ trait TypeAssigner {
def assignType(tree: untpd.OrTypeTree, left: Tree, right: Tree)(implicit ctx: Context) =
tree.withType(left.tpe | right.tpe)
- // RefinedTypeTree is missing, handled specially in Typer and Unpickler.
+ /** Assign type of RefinedType.
+ * Refinements are typed as if they were members of refinement class `refineCls`.
+ */
+ def assignType(tree: untpd.RefinedTypeTree, parent: Tree, refinements: List[Tree], refineCls: ClassSymbol)(implicit ctx: Context) = {
+ def addRefinement(parent: Type, refinement: Tree): Type = {
+ val rsym = refinement.symbol
+ val rinfo = if (rsym is Accessor) rsym.info.resultType else rsym.info
+ RefinedType(parent, rsym.name, rinfo)
+ }
+ val refined = (parent.tpe /: refinements)(addRefinement)
+ tree.withType(RecType.closeOver(rt => refined.substThis(refineCls, RecThis(rt))))
+ }
def assignType(tree: untpd.AppliedTypeTree, tycon: Tree, args: List[Tree])(implicit ctx: Context) = {
val tparams = tycon.tpe.typeParams
@@ -456,7 +467,7 @@ trait TypeAssigner {
}
def assignType(tree: untpd.PolyTypeTree, tparamDefs: List[TypeDef], body: Tree)(implicit ctx: Context) =
- tree.withType(PolyType.fromSymbols(tparamDefs.map(_.symbol), body.tpe))
+ tree.withType(body.tpe.LambdaAbstract(tparamDefs.map(_.symbol)))
def assignType(tree: untpd.ByNameTypeTree, result: Tree)(implicit ctx: Context) =
tree.withType(ExprType(result.tpe))
diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala
index 0ee9a2799..64936e106 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -1008,23 +1008,16 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
val refineCls = createSymbol(refineClsDef).asClass
val TypeDef(_, impl: Template) = typed(refineClsDef)
val refinements1 = impl.body
- val seen = mutable.Set[Symbol]()
assert(tree.refinements.length == refinements1.length, s"${tree.refinements} != $refinements1")
- def addRefinement(parent: Type, refinement: Tree): Type = {
+ val seen = mutable.Set[Symbol]()
+ for (refinement <- refinements1) { // TODO: get clarity whether we want to enforce these conditions
typr.println(s"adding refinement $refinement")
checkRefinementNonCyclic(refinement, refineCls, seen)
val rsym = refinement.symbol
if (rsym.is(Method) && rsym.allOverriddenSymbols.isEmpty)
- ctx.error(i"refinement $rsym without matching type in parent $parent", refinement.pos)
- val rinfo = if (rsym is Accessor) rsym.info.resultType else rsym.info
- RefinedType(parent, rsym.name, rinfo)
- // todo later: check that refinement is within bounds
+ ctx.error(i"refinement $rsym without matching type in parent $tpt1", refinement.pos)
}
- val refined = (tpt1.tpe /: refinements1)(addRefinement)
- val res = cpy.RefinedTypeTree(tree)(tpt1, refinements1).withType(
- RecType.closeOver(rt => refined.substThis(refineCls, RecThis(rt))))
- typr.println(i"typed refinement: ${res.tpe}")
- res
+ assignType(cpy.RefinedTypeTree(tree)(tpt1, refinements1), tpt1, refinements1, refineCls)
}
def typedAppliedTypeTree(tree: untpd.AppliedTypeTree)(implicit ctx: Context): Tree = track("typedAppliedTypeTree") {
@@ -1192,7 +1185,15 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(implicit ctx: Context): Tree = track("typedTypeDef") {
val TypeDef(name, rhs) = tdef
completeAnnotations(tdef, sym)
- assignType(cpy.TypeDef(tdef)(name, typedType(rhs), Nil), sym)
+ val rhs1 = tdef.rhs match {
+ case rhs @ PolyTypeTree(tparams, body) =>
+ val tparams1 = tparams.map(typed(_)).asInstanceOf[List[TypeDef]]
+ val body1 = typedType(body)
+ assignType(cpy.PolyTypeTree(rhs)(tparams1, body1), tparams1, body1)
+ case rhs =>
+ typedType(rhs)
+ }
+ assignType(cpy.TypeDef(tdef)(name, rhs1), sym)
}
def typedClassDef(cdef: untpd.TypeDef, cls: ClassSymbol)(implicit ctx: Context) = track("typedClassDef") {
@@ -1257,7 +1258,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
.withType(dummy.nonMemberTermRef)
checkVariance(impl1)
if (!cls.is(AbstractOrTrait) && !ctx.isAfterTyper) checkRealizableBounds(cls.typeRef, cdef.namePos)
- val cdef1 = assignType(cpy.TypeDef(cdef)(name, impl1, Nil), cls)
+ val cdef1 = assignType(cpy.TypeDef(cdef)(name, impl1), cls)
if (ctx.phase.isTyper && cdef1.tpe.derivesFrom(defn.DynamicClass) && !ctx.dynamicsEnabled) {
val isRequired = parents1.exists(_.tpe.isRef(defn.DynamicClass))
ctx.featureWarning(nme.dynamics.toString, "extension of type scala.Dynamic", isScala2Feature = true,
diff --git a/test/test/DeSugarTest.scala b/test/test/DeSugarTest.scala
index 1365f3222..d7a056e42 100644
--- a/test/test/DeSugarTest.scala
+++ b/test/test/DeSugarTest.scala
@@ -62,7 +62,7 @@ class DeSugarTest extends ParserTest {
case tree1 @ DefDef(name, tparams, vparamss, tpt, _) =>
cpy.DefDef(tree1)(name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt, Type), transform(tree1.rhs))
case tree1 @ TypeDef(name, rhs) =>
- cpy.TypeDef(tree1)(name, transform(rhs, Type), transformSub(tree1.tparams))
+ cpy.TypeDef(tree1)(name, transform(rhs, Type))
case impl @ Template(constr, parents, self, _) =>
cpy.Template(tree1)(transformSub(constr), transform(parents), transformSub(self), transform(impl.body, Expr))
case Thicket(trees) =>
diff --git a/tests/neg/i1605.scala b/tests/neg/i1605.scala
index 776f2df47..f5fd9f29b 100644
--- a/tests/neg/i1605.scala
+++ b/tests/neg/i1605.scala
@@ -1,5 +1,5 @@
object Test {
def foo = inlineMe
- inline def inlineMe = 1 + x // error
+ inline def inlineMe = 1 + x2233 // error
}
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 = ""
+}*/
+