From ee93df064b8b48f9e600d5ea99a0ebc5e0848345 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Mon, 23 Jul 2012 11:14:47 +0200 Subject: SI-4440 workaround: avoid outer accessor that'll vanish outer accessors of final classes are dropped in constructors apply some foresight in explicit outer and replace those doomed outer checks by `true` (since this is unfortunate, we generate an unchecked warning) --- .../scala/tools/nsc/transform/ExplicitOuter.scala | 50 +++++++++++----------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index afbe528b1f..1f7c34b8ad 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -377,6 +377,7 @@ abstract class ExplicitOuter extends InfoTransform } } + // requires settings.XoldPatmat.value def matchTranslation(tree: Match) = { val Match(selector, cases) = tree var nselector = transform(selector) @@ -519,33 +520,32 @@ abstract class ExplicitOuter extends InfoTransform super.transform(treeCopy.Apply(tree, sel, outerVal :: args)) // entry point for pattern matcher translation - case mch: Match if (!opt.virtPatmat) => // don't use old pattern matcher as fallback when the user wants the virtualizing one - matchTranslation(mch) - - case _ => - if (opt.virtPatmat) { // this turned out to be expensive, hence the hacky `if` and `return` - tree match { - // for patmatvirtualiser - // base..eq(o) --> base.$outer().eq(o) if there's an accessor, else the whole tree becomes TRUE - // TODO remove the synthetic `` method from outerFor?? - case Apply(eqsel@Select(eqapp@Apply(sel@Select(base, outerAcc), Nil), eq), args) if outerAcc == nme.OUTER_SYNTH => - val outerFor = sel.symbol.owner.toInterface // TODO: toInterface necessary? - val acc = outerAccessor(outerFor) - if(acc == NoSymbol) { - // println("WARNING: no outer for "+ outerFor) - return transform(TRUE) // urgh... drop condition if there's no accessor - } else { - // println("(base, acc)= "+(base, acc)) - val outerSelect = localTyper typed Apply(Select(base, acc), Nil) - // achieves the same as: localTyper typed atPos(tree.pos)(outerPath(base, base.tpe.typeSymbol, outerFor.outerClass)) - // println("(b, tpsym, outerForI, outerFor, outerClass)= "+ (base, base.tpe.typeSymbol, outerFor, sel.symbol.owner, outerFor.outerClass)) - // println("outerSelect = "+ outerSelect) - return transform(treeCopy.Apply(tree, treeCopy.Select(eqsel, outerSelect, eq), args)) - } - case _ => - } + case m: Match if settings.XoldPatmat.value => // the new pattern matcher runs in its own phase right after typer + matchTranslation(m) + + // for the new pattern matcher + // base..eq(o) --> base.$outer().eq(o) if there's an accessor, else the whole tree becomes TRUE + // TODO remove the synthetic `` method from outerFor?? + case Apply(eqsel@Select(eqapp@Apply(sel@Select(base, nme.OUTER_SYNTH), Nil), eq), args) if !settings.XoldPatmat.value => + val outerFor = sel.symbol.owner.toInterface // TODO: toInterface necessary? + val acc = outerAccessor(outerFor) + + if (acc == NoSymbol || + // since we can't fix SI-4440 properly (we must drop the outer accessors of final classes when there's no immediate reference to them in sight) + // at least don't crash... this duplicates maybeOmittable from constructors + (acc.owner.isEffectivelyFinal && !acc.isOverridingSymbol)) { + unit.uncheckedWarning(tree.pos, "The outer reference in this type test cannot be checked at run time.") + return transform(TRUE) // urgh... drop condition if there's no accessor (or if it may disappear after constructors) + } else { + // println("(base, acc)= "+(base, acc)) + val outerSelect = localTyper typed Apply(Select(base, acc), Nil) + // achieves the same as: localTyper typed atPos(tree.pos)(outerPath(base, base.tpe.typeSymbol, outerFor.outerClass)) + // println("(b, tpsym, outerForI, outerFor, outerClass)= "+ (base, base.tpe.typeSymbol, outerFor, sel.symbol.owner, outerFor.outerClass)) + // println("outerSelect = "+ outerSelect) + return transform(treeCopy.Apply(tree, treeCopy.Select(eqsel, outerSelect, eq), args)) } + case _ => if (settings.Xmigration28.value) tree match { case TypeApply(fn @ Select(qual, _), args) if fn.symbol == Object_isInstanceOf || fn.symbol == Any_isInstanceOf => if (isArraySeqTest(qual.tpe, args.head.tpe)) -- cgit v1.2.3