diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Delambdafy.scala | 17 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Erasure.scala | 40 |
2 files changed, 36 insertions, 21 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala index 933a2f70a1..d81a5d5755 100644 --- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala +++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala @@ -232,6 +232,10 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre val parents = addSerializable(abstractFunctionErasedType) val funOwner = originalFunction.symbol.owner + // TODO harmonize the naming of delamdafy anon-fun classes with those spun up by Uncurry + // - make `anonClass.isAnonymousClass` true. + // - use `newAnonymousClassSymbol` or push the required variations into a similar factory method + // - reinstate the assertion in `Erasure.resolveAnonymousBridgeClash` val suffix = "$lambda$" + ( if (funOwner.isPrimaryConstructor) "" else "$" + funOwner.name @@ -282,18 +286,11 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre if (sym == NoSymbol) sym.toString else s"$sym: ${sym.tpe} in ${sym.owner}" - def clashError(bm: Symbol) = { - unit.error( - applyMethodDef.symbol.pos, - sm"""bridge generated for member ${fulldef(applyMethodDef.symbol)} - |which overrides ${fulldef(getMember(abstractFunctionErasedType.typeSymbol, nme.apply))} - |clashes with definition of the member itself; - |both have erased type ${exitingPostErasure(bm.tpe)}""") - } - bridgeMethod foreach (bm => + // TODO SI-6260 maybe just create the apply method with the signature (Object => Object) in all cases + // rather than the method+bridge pair. if (bm.symbol.tpe =:= applyMethodDef.symbol.tpe) - clashError(bm.symbol) + erasure.resolveAnonymousBridgeClash(applyMethodDef.symbol, bm.symbol) ) val body = members ++ List(constr, applyMethodDef) ++ bridgeMethod diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index ccfddab94a..60c1553ef3 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -403,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) @@ -440,7 +440,7 @@ abstract class Erasure extends AddInterfaces } } } - noclash + clashErrors } /** TODO - work through this logic with a fine-toothed comb, incorporating @@ -478,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)) @@ -1127,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) } |