diff options
author | Grzegorz Kossakowski <grzegorz.kossakowski@gmail.com> | 2014-02-10 18:27:17 +0100 |
---|---|---|
committer | Grzegorz Kossakowski <grzegorz.kossakowski@gmail.com> | 2014-02-10 18:27:17 +0100 |
commit | 6c73837668cb961b50f5f523aa0a5d6fe4d849c3 (patch) | |
tree | 9865c31c7a1acb7548048eefb0af1054f3c6639b /src/compiler | |
parent | 4ffbb06566fab0fe4dc2ed00800b13656cc8fea3 (diff) | |
parent | d6b1e6e4ff1cb477e9b26ba7e1a02d1ea98fa132 (diff) | |
download | scala-6c73837668cb961b50f5f523aa0a5d6fe4d849c3.tar.gz scala-6c73837668cb961b50f5f523aa0a5d6fe4d849c3.tar.bz2 scala-6c73837668cb961b50f5f523aa0a5d6fe4d849c3.zip |
Merge pull request #3428 from retronym/ticket/6260
SI-6260 Avoid double-def error with lambdas over value classes
Diffstat (limited to 'src/compiler')
-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) } |