aboutsummaryrefslogtreecommitdiff
path: root/src/dotty
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2014-09-25 13:25:06 +0200
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2014-10-11 06:38:11 +0200
commit543ff7f4123ded7172fd6ede59f09945efd7c158 (patch)
tree1c14165b391ca2b6de15f5a584fc804474ada13e /src/dotty
parent167581469779cabc7138427d506a16507369cbf5 (diff)
downloaddotty-543ff7f4123ded7172fd6ede59f09945efd7c158.tar.gz
dotty-543ff7f4123ded7172fd6ede59f09945efd7c158.tar.bz2
dotty-543ff7f4123ded7172fd6ede59f09945efd7c158.zip
Make changeOwner more robust regarding non-standard owner chains
The problem is running changeOwner(from, to) where - from is a ValDef or a Label - an embedded definition has as owner not `from` but some owner of `from`. We allow such denomrlaized owners and the pattern matcher generates them. This patch makes changeOwner take these situations into account.
Diffstat (limited to 'src/dotty')
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala15
-rw-r--r--src/dotty/tools/dotc/core/Flags.scala3
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala25
-rw-r--r--src/dotty/tools/dotc/transform/TreeChecker.scala15
4 files changed, 41 insertions, 17 deletions
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index 101631738..e4450da89 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -525,8 +525,19 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def subst(from: List[Symbol], to: List[Symbol])(implicit ctx: Context): ThisTree =
new TreeTypeMap(substFrom = from, substTo = to).apply(tree)
- def changeOwner(from: Symbol, to: Symbol)(implicit ctx: Context): ThisTree =
- new TreeTypeMap(oldOwners = from :: Nil, newOwners = to :: Nil).apply(tree)
+ /** Change owner from `from` to `to`. If `from` is a weak owner, also change its
+ * owner to `to`, and continue until a non-weak owner is reached.
+ */
+ def changeOwner(from: Symbol, to: Symbol)(implicit ctx: Context): ThisTree = {
+ def loop(from: Symbol, froms: List[Symbol], tos: List[Symbol]): ThisTree = {
+ if (from.isWeakOwner) loop(from.owner, from :: froms, to :: tos)
+ else {
+ //println(i"change owner ${from :: froms}%, % ==> $tos of $tree")
+ new TreeTypeMap(oldOwners = from :: froms, newOwners = tos).apply(tree)
+ }
+ }
+ loop(from, Nil, to :: Nil)
+ }
def select(name: Name)(implicit ctx: Context): Select =
Select(tree, name)
diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala
index 896de25fd..e34483f8f 100644
--- a/src/dotty/tools/dotc/core/Flags.scala
+++ b/src/dotty/tools/dotc/core/Flags.scala
@@ -501,6 +501,9 @@ object Flags {
/** Either mutable or lazy */
final val MutableOrLazy = Mutable | Lazy
+ /** Either method or lazy */
+ final val MethodOrLazy = Method | Lazy
+
/** Labeled `private` or `final` */
final val PrivateOrFinal = Private | Final
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 12a08a112..d0053e679 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -279,8 +279,8 @@ object SymDenotations {
do {
owner = owner.owner
sep += separator
- } while (!owner.isClass)
- val fn = owner.skipPackageObject.fullNameSeparated(separator) ++ sep ++ name
+ } while (!owner.isClass && !owner.isPackageObject)
+ val fn = owner.fullNameSeparated(separator) ++ sep ++ name
if (isType) fn.toTypeName else fn.toTermName
}
@@ -562,6 +562,15 @@ object SymDenotations {
result
}
+ /** Symbol is an owner that would be skipped by effectiveOwner. Skipped are
+ * - package objects
+ * - labels
+ * - non-lazy valdefs
+ */
+ def isWeakOwner(implicit ctx: Context): Boolean =
+ isPackageObject ||
+ isTerm && !is(MethodOrLazy, butNot = Label) && !isLocalDummy
+
// def isOverridable: Boolean = !!! need to enforce that classes cannot be redefined
// def isSkolem: Boolean = ???
@@ -625,14 +634,12 @@ object SymDenotations {
}
}
- /** If this is a package object or its implementing class, its owner,
- * otherwise the denoting symbol.
- */
- final def skipPackageObject(implicit ctx: Context): Symbol =
- if (isPackageObject) owner else symbol
+ /** If this is a weak owner, its owner, otherwise the denoting symbol. */
+ final def skipWeakOwner(implicit ctx: Context): Symbol =
+ if (isWeakOwner) owner.skipWeakOwner else symbol
- /** The owner, skipping package objects. */
- final def effectiveOwner(implicit ctx: Context) = owner.skipPackageObject
+ /** The owner, skipping package objects, labels and non-lazy valdefs. */
+ final def effectiveOwner(implicit ctx: Context) = owner.skipWeakOwner
/** The class containing this denotation.
* If this denotation is already a class, return itself
diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala
index cf32df61b..ef5baca07 100644
--- a/src/dotty/tools/dotc/transform/TreeChecker.scala
+++ b/src/dotty/tools/dotc/transform/TreeChecker.scala
@@ -97,14 +97,13 @@ class TreeChecker {
}
private def checkOwner(tree: untpd.Tree)(implicit ctx: Context): Unit = {
- def ownerMatches(symOwner: Symbol, ctxOwner: Symbol): Boolean = {
+ def ownerMatches(symOwner: Symbol, ctxOwner: Symbol): Boolean =
symOwner == ctxOwner ||
- ctxOwner.isTerm && (!(ctxOwner is Method | Lazy | Mutable) || (ctxOwner is Label)) &&
- ownerMatches(symOwner, ctxOwner.owner)
- }
+ ctxOwner.isWeakOwner && ownerMatches(symOwner, ctxOwner.owner)
if(!ownerMatches(tree.symbol.owner, ctx.owner)) {
assert(ownerMatches(tree.symbol.owner, ctx.owner),
- i"bad owner; ${tree.symbol} has owner ${tree.symbol.owner}, expected was ${ctx.owner}")
+ i"bad owner; ${tree.symbol} has owner ${tree.symbol.owner}, expected was ${ctx.owner}\n" +
+ i"owner chain = ${tree.symbol.ownersIterator.toList}%, %, ctxOwners = ${ctx.outersIterator.map(_.owner).toList}%, %")
}
}
@@ -123,7 +122,11 @@ class TreeChecker {
* of a helper value without having to do a change owner traversal of the expression.
*/
override def typedStats(trees: List[untpd.Tree], exprOwner: Symbol)(implicit ctx: Context): List[Tree] = {
- for (tree <- trees if tree.isDef) checkOwner(tree)
+ for (tree <- trees) tree match {
+ case tree: untpd.DefTree => checkOwner(tree)
+ case _: untpd.Thicket => assert(false, "unexpanded thicket in statement sequence")
+ case _ =>
+ }
super.typedStats(trees, exprOwner)
}