diff options
author | Aleksandar Prokopec <axel22@gmail.com> | 2012-05-18 13:46:30 +0200 |
---|---|---|
committer | Aleksandar Prokopec <axel22@gmail.com> | 2012-05-18 13:54:51 +0200 |
commit | 2aa685bcbf38b69ff52cf915a013f3f200a8fa7c (patch) | |
tree | b7c61842afdd32c2e8e4d937d5ca4f4a054d2e9a /src/compiler | |
parent | c7699ebe45820a34de2e9f5c9bfba3dea6b56bd3 (diff) | |
download | scala-2aa685bcbf38b69ff52cf915a013f3f200a8fa7c.tar.gz scala-2aa685bcbf38b69ff52cf915a013f3f200a8fa7c.tar.bz2 scala-2aa685bcbf38b69ff52cf915a013f3f200a8fa7c.zip |
Fixes SI-4717.
A lazy val declared inside an anonymous class inside a specialized
context no longer crashes Duplicators.
Previously, a duplicated lazy val was assigned to the wrong owner
in Duplicators:
def x[B >: A]: Unit = new Bounds[B] {
lazy val it = ??? // def or val okay
}
Above, the `it` in `$anon` in `x$mcZ$sp` had its owner set to `x$mcZ$sp`
instead of `$anon`. This crashed the typer when it had to retype its
lazy accessor, because there was no `lazy var it` in `$anon$`.
Furthermore, the duplicated symbol wasn't being added to the list of
declarations of `$anon`.
Changes:
1) `invalidate` in Duplicators takes an additional parameter which is
the new owner of the new symbol that has to be duplicated. If this parameter
is set to `NoSymbol`, then the new owner is `context.owner`, as before.
2) the newly created lazy val symbol is being added to the list of
declarations of its new owner.
Removes debugging output from the previous commit.
Review by dragos.
@mention dragos
Diffstat (limited to 'src/compiler')
3 files changed, 20 insertions, 32 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 5a5e891620..e0f34b47c8 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -1550,7 +1550,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { val meth = addBody(tree, source) val d = new Duplicator - log("-->d DUPLICATING: " + meth) + debuglog("-->d DUPLICATING: " + meth) d.retyped( localTyper.context1.asInstanceOf[d.Context], meth, diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala index 52335f85e1..ce23885643 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala @@ -143,8 +143,8 @@ abstract class Duplicators extends Analyzer { else sym - private def invalidate(tree: Tree) { - log("attempting to invalidate " + tree.symbol + ", owner - " + (if (tree.symbol ne null) tree.symbol.owner else "<NULL>")) + private def invalidate(tree: Tree, owner: Symbol = NoSymbol) { + debuglog("attempting to invalidate " + tree.symbol) if (tree.isDef && tree.symbol != NoSymbol) { debuglog("invalid " + tree.symbol) invalidSyms(tree.symbol) = tree @@ -158,18 +158,20 @@ abstract class Duplicators extends Analyzer { newsym.setInfo(fixType(ldef.symbol.info)) ldef.symbol = newsym debuglog("newsym: " + newsym + " info: " + newsym.info) - + case vdef @ ValDef(mods, name, _, rhs) if mods.hasFlag(Flags.LAZY) => - log("ValDef " + name + " sym.info: " + vdef.symbol.info + ", owner: " + vdef.symbol.owner + " vs. context owner: " + context.owner) + debuglog("ValDef " + name + " sym.info: " + vdef.symbol.info) invalidSyms(vdef.symbol) = vdef - val newsym = vdef.symbol.cloneSymbol(context.owner) + val newowner = if (owner != NoSymbol) owner else context.owner + val newsym = vdef.symbol.cloneSymbol(newowner) newsym.setInfo(fixType(vdef.symbol.info)) vdef.symbol = newsym - log("newsym: " + newsym + " info: " + newsym.info + ", " + newsym.owner + ", whereas symbol.owner is: " + vdef.symbol.owner) - + newsym.owner.info.decls enter newsym + debuglog("newsym: " + newsym + " info: " + newsym.info) + case DefDef(_, name, tparams, vparamss, _, rhs) => // invalidate parameters - invalidate(tparams ::: vparamss.flatten) + invalidateAll(tparams ::: vparamss.flatten) tree.symbol = NoSymbol case _ => @@ -178,14 +180,14 @@ abstract class Duplicators extends Analyzer { } } - private def invalidate(stats: List[Tree]) { - stats foreach invalidate + private def invalidateAll(stats: List[Tree], owner: Symbol = NoSymbol) { + stats.foreach(invalidate(_, owner)) } def retypedMethod(ddef: DefDef, oldThis: Symbol, newThis: Symbol): Tree = { oldClassOwner = oldThis newClassOwner = newThis - invalidate(ddef.tparams) + invalidateAll(ddef.tparams) mforeach(ddef.vparamss) { vdef => invalidate(vdef) vdef.tpe = null @@ -239,15 +241,15 @@ abstract class Duplicators extends Analyzer { case Block(stats, res) => debuglog("invalidating block") - invalidate(stats) + invalidateAll(stats) invalidate(res) tree.tpe = null super.typed(tree, mode, pt) case ClassDef(_, _, _, tmpl @ Template(parents, _, stats)) => - log("invalidating classdef " + tree.tpe) + // log("invalidating classdef " + tree) tmpl.symbol = tree.symbol.newLocalDummy(tree.pos) - invalidate(stats) + invalidateAll(stats, tree.symbol) tree.tpe = null super.typed(tree, mode, pt) @@ -257,7 +259,6 @@ abstract class Duplicators extends Analyzer { super.typed(ddef, mode, pt) case vdef @ ValDef(mods, name, tpt, rhs) => - log("vdef: " + vdef) // log("vdef fixing tpe: " + tree.tpe + " with sym: " + tree.tpe.typeSymbol + " and " + invalidSyms) //if (mods.hasFlag(Flags.LAZY)) vdef.symbol.resetFlag(Flags.MUTABLE) // Martin to Iulian: lazy vars can now appear because they are no longer boxed; Please check that deleting this statement is OK. vdef.tpt.tpe = fixType(vdef.tpt.tpe) @@ -359,15 +360,11 @@ abstract class Duplicators extends Analyzer { tree case _ => - log("Duplicators default case: " + tree.summaryString) + debuglog("Duplicators default case: " + tree.summaryString) if (tree.hasSymbol && tree.symbol != NoSymbol && (tree.symbol.owner == definitions.AnyClass)) { tree.symbol = NoSymbol // maybe we can find a more specific member in a subclass of Any (see AnyVal members, like ==) } tree.tpe = null - tree match { - case Select(q, n) => log("Select: " + q + ", " + n + " = " + q.tpe.member(n) + ", members: " + q.tpe.members) - case _ => log(tree.getClass) - } super.typed(tree, mode, pt) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index aa0a776327..8c2eae1c86 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3657,10 +3657,6 @@ trait Typers extends Modes with Adaptations with Taggings { def typed1(tree: Tree, mode: Int, pt: Type): Tree = { def isPatternMode = inPatternMode(mode) - tree match { - case This(_) => log("typed1: " + tree + ", " + tree.tpe) - case _ => - } //Console.println("typed1("+tree.getClass()+","+Integer.toHexString(mode)+","+pt+")") //@M! get the type of the qualifier in a Select tree, otherwise: NoType @@ -4239,7 +4235,6 @@ trait Typers extends Modes with Adaptations with Taggings { def typedThis(qual: Name) = tree.symbol orElse qualifyingClass(tree, qual, packageOK = false) match { case NoSymbol => tree case clazz => - log("typedThis: " + qual + ", " + clazz.thisType.underlying) tree setSymbol clazz setType clazz.thisType.underlying if (isStableContext(tree, mode, pt)) tree setType clazz.thisType else tree } @@ -4252,7 +4247,6 @@ trait Typers extends Modes with Adaptations with Taggings { * @return ... */ def typedSelect(qual: Tree, name: Name): Tree = { - log("typedSelect: " + qual + ", name: " + name + ", member: " + (qual.tpe.members)) def asDynamicCall = dyna.mkInvoke(context.tree, tree, qual, name) map (typed1(_, mode, pt)) val sym = tree.symbol orElse member(qual, name) orElse { @@ -4876,12 +4870,9 @@ trait Typers extends Modes with Adaptations with Taggings { case Select(qual, name) => incCounter(typedSelectCount) - val tpq = typedQualifier(qual, mode) - if (qual.tpe ne null) log("Select: " + qual + ", " + name + " = " + qual.tpe.member(name) + ", members: " + qual.tpe.members) - var qual1 = checkDead(tpq) + var qual1 = checkDead(typedQualifier(qual, mode)) if (name.isTypeName) qual1 = checkStable(qual1) - log("members: " + qual.tpe.members) - + val tree1 = // temporarily use `filter` and an alternative for `withFilter` if (name == nme.withFilter) silent(_ => typedSelect(qual1, name)) match { |