diff options
author | Paul Phillips <paulp@improving.org> | 2013-05-20 21:56:14 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-05-21 01:18:20 -0700 |
commit | a2ad291acd159ed299eb30305e42a0bace95f02a (patch) | |
tree | 63dc189dea7b1096232da0a4e0d0edfdf676578f /src/compiler | |
parent | 085b4d9bdb7ba9f9fe00c63e998e93278a34b161 (diff) | |
download | scala-a2ad291acd159ed299eb30305e42a0bace95f02a.tar.gz scala-a2ad291acd159ed299eb30305e42a0bace95f02a.tar.bz2 scala-a2ad291acd159ed299eb30305e42a0bace95f02a.zip |
SI-3425 erasure crash with refinement members.
Checking that a refinement class symbol does not override
any symbols does mean it will have to be invoke reflectively;
but the converse is not true. It can override other symbols
and still have to be called reflectively, because the
overridden symbols may also be defined in refinement classes.
scala> class Foo { type R1 <: { def x: Any } ; type R2 <: R1 { def x: Int } }
defined class Foo
scala> typeOf[Foo].member(TypeName("R2")).info.member("x": TermName).overrideChain
res1: List[$r.intp.global.Symbol] = List(method x, method x)
scala> res1 filterNot (_.owner.isRefinementClass)
res2: List[$r.intp.global.Symbol] = List()
And checking that "owner.info decl name == this" only works if
name is not overloaded.
So the logic is all in "isOnlyRefinementMember" now, and
let's hope that suffices for a while.
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Erasure.scala | 23 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 4 |
2 files changed, 17 insertions, 10 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index ac79c60254..fd22801897 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -974,7 +974,6 @@ abstract class Erasure extends AddInterfaces case Select(qual, _) => qual case TypeApply(Select(qual, _), _) => qual } - def preEraseAsInstanceOf = { (fn: @unchecked) match { case TypeApply(Select(qual, _), List(targ)) => @@ -1032,8 +1031,9 @@ abstract class Erasure extends AddInterfaces preEraseAsInstanceOf } else if (fn.symbol == Any_isInstanceOf) { preEraseIsInstanceOf - } else if (fn.symbol.owner.isRefinementClass && !fn.symbol.isOverridingSymbol) { - // !!! Another spot where we produce overloaded types (see test run/t6301) + } else if (fn.symbol.isOnlyRefinementMember) { + // !!! Another spot where we produce overloaded types (see test pos/t6301) + log(s"${fn.symbol.fullLocationString} originates in refinement class - call will be implemented via reflection.") ApplyDynamic(qualifier, args) setSymbol fn.symbol setPos tree.pos } else if (fn.symbol.isMethodWithExtension && !fn.symbol.tpe.isErroneous) { Apply(gen.mkAttributedRef(extensionMethods.extensionMethod(fn.symbol)), qualifier :: args) @@ -1161,12 +1161,19 @@ abstract class Erasure extends AddInterfaces preErase(fun) case Select(qual, name) => - val owner = tree.symbol.owner - // println("preXform: "+ (tree, tree.symbol, tree.symbol.owner, tree.symbol.owner.isRefinementClass)) + val sym = tree.symbol + val owner = sym.owner if (owner.isRefinementClass) { - val overridden = tree.symbol.nextOverriddenSymbol - assert(overridden != NoSymbol, tree.symbol) - tree.symbol = overridden + sym.allOverriddenSymbols filterNot (_.owner.isRefinementClass) match { + case overridden :: _ => + log(s"${sym.fullLocationString} originates in refinement class - replacing with ${overridden.fullLocationString}.") + tree.symbol = overridden + case Nil => + // Ideally this should not be reached or reachable; anything which would + // get here should have been caught in the surrounding Apply. + devWarning(s"Failed to rewrite reflective apply - now don't know what to do with " + tree) + return treeCopy.Select(tree, gen.mkAttributedCast(qual, qual.tpe.widen), name) + } } def isAccessible(sym: Symbol) = localTyper.context.isAccessible(sym, sym.owner.thisType) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 8511428d90..f879d11b0b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -2873,8 +2873,8 @@ trait Typers extends Adaptations with Tags { templ updateAttachment att.copy(stats = stats1) for (stat <- stats1 if stat.isDef && stat.symbol.isOverridingSymbol) stat.symbol setFlag OVERRIDE - } - } + } + } def typedImport(imp : Import) : Import = (transformed remove imp) match { case Some(imp1: Import) => imp1 |