From 1890a4175dc6c436b37ddc8c6b74e036b9c6328c Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Thu, 29 Mar 2012 16:06:42 +0200 Subject: specialization: see outer contexts to fix symbols this corner case in Duplicators is hit when compiling the new AbstractPartialFunction (which is specialized) under -Yvirtpatmat TODO: why do we need to guard against cx.scope eq null in typers? review by @vladureche --- .../scala/tools/nsc/typechecker/Duplicators.scala | 16 +++++++++++++++- src/compiler/scala/tools/nsc/typechecker/Typers.scala | 2 +- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala index eb0d489901..f6d1e42c32 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala @@ -79,7 +79,17 @@ abstract class Duplicators extends Analyzer { override def mapOver(tpe: Type): Type = tpe match { case TypeRef(NoPrefix, sym, args) if sym.isTypeParameterOrSkolem => - val sym1 = context.scope.lookup(sym.name) + var sym1 = context.scope.lookup(sym.name) + if (sym1 eq NoSymbol) { + // try harder (look in outer scopes) + // with virtpatmat, this can happen when the sym is referenced in the scope of a LabelDef but is defined in the scope of an outer DefDef (e.g., in AbstractPartialFunction's andThen) + BodyDuplicator.super.silent(_.typedType(Ident(sym.name))) match { + case SilentResultValue(t) => + sym1 = t.symbol + debuglog("fixed by trying harder: "+(sym, sym1, context)) + case _ => + } + } // assert(sym1 ne NoSymbol, tpe) if ((sym1 ne NoSymbol) && (sym1 ne sym)) { debuglog("fixing " + sym + " -> " + sym1) @@ -255,7 +265,10 @@ abstract class Duplicators extends Analyzer { case ldef @ LabelDef(name, params, rhs) => // log("label def: " + ldef) + // in case the rhs contains any definitions -- TODO: is this necessary? + invalidate(rhs) ldef.tpe = null + // since typer does not create the symbols for a LabelDef's params, // we do that manually here -- we should really refactor LabelDef to be a subclass of DefDef def newParam(p: Tree): Ident = { @@ -265,6 +278,7 @@ abstract class Duplicators extends Analyzer { val params1 = params map newParam val rhs1 = (new TreeSubstituter(params map (_.symbol), params1) transform rhs) // TODO: duplicate? rhs1.tpe = null + super.typed(treeCopy.LabelDef(tree, name, params1, rhs1), mode, pt) case Bind(name, _) => diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index a9c9dfab6a..7d2e587b3f 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -4183,7 +4183,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { var defEntry: ScopeEntry = null // the scope entry of defSym, if defined in a local scope var cx = startingIdentContext - while (defSym == NoSymbol && cx != NoContext) { + while (defSym == NoSymbol && cx != NoContext && (cx.scope ne null)) { // cx.scope eq null arises during FixInvalidSyms in Duplicators // !!! Shouldn't the argument to compileSourceFor be cx, not context? // I can't tell because those methods do nothing in the standard compiler, // presumably they are overridden in the IDE. -- cgit v1.2.3