diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/transform/Erasure.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Erasure.scala | 65 |
1 files changed, 48 insertions, 17 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 6732900ef2..60c1553ef3 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -61,7 +61,7 @@ abstract class Erasure extends AddInterfaces parents foreach traverse case ClassInfoType(parents, _, _) => parents foreach traverse - case AnnotatedType(_, atp, _) => + case AnnotatedType(_, atp) => traverse(atp) case _ => mapOver(tp) @@ -92,11 +92,22 @@ abstract class Erasure extends AddInterfaces // more rigorous way up front rather than catching it after the fact, // but that will be more involved. private def dotCleanup(sig: String): String = { + // OPT 50% of time in generic signatures (~1% of compile time) was in this method, hence the imperative rewrite. var last: Char = '\u0000' - sig map { - case '.' if last != '>' => last = '.' ; '$' - case ch => last = ch ; ch + var i = 0 + val len = sig.length + val copy: Array[Char] = sig.toCharArray + var changed = false + while (i < sig.length) { + val ch = copy(i) + if (ch == '.' && last != '>') { + copy(i) = '$' + changed = true + } + last = ch + i += 1 } + if (changed) new String(copy) else sig } /** This object is only used for sanity testing when -check:genjvm is set. @@ -302,7 +313,7 @@ abstract class Erasure extends AddInterfaces boxedSig(parent) case ClassInfoType(parents, _, _) => superSig(parents) - case AnnotatedType(_, atp, _) => + case AnnotatedType(_, atp) => jsig(atp, existentiallyBound, toplevel, primitiveOK) case BoundedWildcardType(bounds) => println("something's wrong: "+sym0+":"+sym0.tpe+" has a bounded wildcard type") @@ -392,19 +403,19 @@ abstract class Erasure extends AddInterfaces * @param other The overidden symbol for which the bridge was generated * @param bridge The bridge */ - def checkBridgeOverrides(member: Symbol, other: Symbol, bridge: Symbol): Boolean = { + def checkBridgeOverrides(member: Symbol, other: Symbol, bridge: Symbol): Seq[(Position, String)] = { def fulldef(sym: Symbol) = if (sym == NoSymbol) sym.toString else s"$sym: ${sym.tpe} in ${sym.owner}" var noclash = true + val clashErrors = mutable.Buffer[(Position, String)]() def clashError(what: String) = { - noclash = false - unit.error( - if (member.owner == root) member.pos else root.pos, - sm"""bridge generated for member ${fulldef(member)} - |which overrides ${fulldef(other)} - |clashes with definition of $what; - |both have erased type ${exitingPostErasure(bridge.tpe)}""") + val pos = if (member.owner == root) member.pos else root.pos + val msg = sm"""bridge generated for member ${fulldef(member)} + |which overrides ${fulldef(other)} + |clashes with definition of $what; + |both have erased type ${exitingPostErasure(bridge.tpe)}""" + clashErrors += Tuple2(pos, msg) } for (bc <- root.baseClasses) { if (settings.debug) @@ -429,7 +440,7 @@ abstract class Erasure extends AddInterfaces } } } - noclash + clashErrors } /** TODO - work through this logic with a fine-toothed comb, incorporating @@ -467,8 +478,18 @@ abstract class Erasure extends AddInterfaces bridge setInfo (otpe cloneInfo bridge) bridgeTarget(bridge) = member - if (!(member.tpe exists (_.typeSymbol.isDerivedValueClass)) || - checkBridgeOverrides(member, other, bridge)) { + def sigContainsValueClass = (member.tpe exists (_.typeSymbol.isDerivedValueClass)) + + val shouldAdd = ( + !sigContainsValueClass + || (checkBridgeOverrides(member, other, bridge) match { + case Nil => true + case es if member.owner.isAnonymousClass => resolveAnonymousBridgeClash(member, bridge); true + case es => for ((pos, msg) <- es) unit.error(pos, msg); false + }) + ) + + if (shouldAdd) { exitingErasure(root.info.decls enter bridge) if (other.owner == root) { exitingErasure(root.info.decls.unlink(other)) @@ -522,6 +543,8 @@ abstract class Erasure extends AddInterfaces class Eraser(_context: Context) extends Typer(_context) with TypeAdapter { val typer = this.asInstanceOf[analyzer.Typer] + override protected def stabilize(tree: Tree, pre: Type, mode: Mode, pt: Type): Tree = tree + /** Replace member references as follows: * * - `x == y` for == in class Any becomes `x equals y` with equals in class Object. @@ -760,7 +783,7 @@ abstract class Erasure extends AddInterfaces || super.exclude(sym) || !sym.hasTypeAt(currentRun.refchecksPhase.id) ) - override def matches(sym1: Symbol, sym2: Symbol) = true + override def matches(lo: Symbol, high: Symbol) = true } def isErasureDoubleDef(pair: SymbolPair) = { import pair._ @@ -1114,5 +1137,13 @@ abstract class Erasure extends AddInterfaces } } + final def resolveAnonymousBridgeClash(sym: Symbol, bridge: Symbol) { + // TODO reinstate this after Delambdafy generates anonymous classes that meet this requirement. + // require(sym.owner.isAnonymousClass, sym.owner) + log(s"Expanding name of ${sym.debugLocationString} as it clashes with bridge. Renaming deemed safe because the owner is anonymous.") + sym.expandName(sym.owner) + bridge.resetFlag(BRIDGE) + } + private class TypeRefAttachment(val tpe: TypeRef) } |