aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-11-07 21:38:30 +0100
committerMartin Odersky <odersky@gmail.com>2013-11-07 21:38:30 +0100
commit514801453e240610a0ba68fff7305355a7d204e1 (patch)
tree98b840cef13449dd8f280c576f5620ecec557061
parent44267a9abc74de11e76ecd2ae7bf1cb0d0152043 (diff)
downloaddotty-514801453e240610a0ba68fff7305355a7d204e1.tar.gz
dotty-514801453e240610a0ba68fff7305355a7d204e1.tar.bz2
dotty-514801453e240610a0ba68fff7305355a7d204e1.zip
Fixing NoPosition leaks
Previously, some trees could contain subtrees with NoPosition. This happended when a tree had both positioned children and other children with NoPosition. When setting the synthetic position of a tree, the NoPosition children were not visited.
-rw-r--r--src/dotty/tools/dotc/ast/Trees.scala44
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala2
2 files changed, 35 insertions, 11 deletions
diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala
index 5ce505133..8677331d6 100644
--- a/src/dotty/tools/dotc/ast/Trees.scala
+++ b/src/dotty/tools/dotc/ast/Trees.scala
@@ -31,19 +31,26 @@ object Trees {
*/
abstract class Positioned extends DotClass with Product {
- private[this] var curPos: Position = initialPos
+ private[this] var curPos: Position = _
+
+ setPos(initialPos)
/** The item's position.
*/
def pos: Position = curPos
- /** Destructively update to given poisition */
- protected def setPos(pos: Position): Unit = curPos = pos
+ /** Destructively update `curPos` to given position. Also, set any missing
+ * positions in children.
+ */
+ protected def setPos(pos: Position): Unit = {
+ curPos = pos
+ if (pos.exists) setChildPositions(pos.toSynthetic)
+ }
/** The envelope containing the item in its entirety. Envelope is different from
* `pos` for definitions (instances of MemberDef).
*/
- def envelope: Position = curPos.toSynthetic
+ def envelope: Position = pos.toSynthetic
/** A positioned item like this one with the position set to `pos`.
* if the positioned item is source-derived, a clone is returned.
@@ -52,8 +59,7 @@ object Trees {
*/
def withPos(pos: Position): this.type = {
val newpd = (if (pos == curPos || curPos.isSynthetic) this else clone).asInstanceOf[Positioned]
- setPos(pos)
- setChildPositions(pos.toSynthetic)
+ newpd.setPos(pos)
newpd.asInstanceOf[this.type]
}
@@ -71,10 +77,7 @@ object Trees {
private def setChildPositions(pos: Position): Unit = {
def deepSetPos(x: Any): Unit = x match {
case p: Positioned =>
- if (!p.pos.exists) {
- p.setPos(pos)
- p.setChildPositions(pos)
- }
+ if (!p.pos.exists) p.setPos(pos)
case xs: List[_] =>
xs foreach deepSetPos
case _ =>
@@ -107,6 +110,27 @@ object Trees {
case (t: Tree[_]) :: xs1 => unionPos(pos union t.envelope, xs1)
case _ => pos
}
+
+ def contains(that: Positioned): Boolean = {
+ def isParent(x: Any): Boolean = x match {
+ case x: Positioned =>
+ x contains that
+ case xs: List[_] =>
+ xs exists isParent
+ case _ =>
+ false
+ }
+ (this eq that) ||
+ (this.envelope contains that.pos) && {
+ var n = productArity
+ var found = false
+ while (n > 0 && !found) {
+ n -= 1
+ found = isParent(productElement(n))
+ }
+ found
+ }
+ }
}
/** Modifiers and annotations for definitions
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index ee0ba93a3..546a3e027 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -80,7 +80,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
def toTextFunction(args: List[Type]): Text =
changePrec(GlobalPrec) {
val argStr: Text =
- if (args.length == 2 && !(defn.TupleClasses contains args.head.typeSymbol))
+ if (args.length == 2 && !defn.isTupleType(args.head))
atPrec(InfixPrec) { toText(args.head) }
else
toTextTuple(args.init)