diff options
author | Martin Odersky <odersky@gmail.com> | 2014-09-25 13:25:06 +0200 |
---|---|---|
committer | Dmitry Petrashko <dmitry.petrashko@gmail.com> | 2014-10-11 06:38:11 +0200 |
commit | 543ff7f4123ded7172fd6ede59f09945efd7c158 (patch) | |
tree | 1c14165b391ca2b6de15f5a584fc804474ada13e /src/dotty | |
parent | 167581469779cabc7138427d506a16507369cbf5 (diff) | |
download | dotty-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.scala | 15 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Flags.scala | 3 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 25 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/TreeChecker.scala | 15 |
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) } |