summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Suereth <Joshua.Suereth@gmail.com>2012-10-31 11:13:22 -0700
committerJosh Suereth <Joshua.Suereth@gmail.com>2012-10-31 11:13:22 -0700
commit17497cbc95d2e3cfe52eb2a1ece0d414e9308660 (patch)
tree353ebfd1a36331cba3661838762da3daaf6adfec
parent4752f1243d5aa316b3a2042b93166647c665ee42 (diff)
parent6740ba7832410baee77afd8189e4f8977a866a2b (diff)
downloadscala-17497cbc95d2e3cfe52eb2a1ece0d414e9308660.tar.gz
scala-17497cbc95d2e3cfe52eb2a1ece0d414e9308660.tar.bz2
scala-17497cbc95d2e3cfe52eb2a1ece0d414e9308660.zip
Merge pull request #1543 from adriaanm/paulp-add-synthetics-once
SI-6578 Harden against synthetics being added more than once.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala31
1 files changed, 25 insertions, 6 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index cc3d980cf1..001acc7a80 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -36,11 +36,31 @@ trait SyntheticMethods extends ast.TreeDSL {
import definitions._
import CODE._
+ private lazy val productSymbols = List(Product_productPrefix, Product_productArity, Product_productElement, Product_iterator, Product_canEqual)
+ private lazy val valueSymbols = List(Any_hashCode, Any_equals)
+ private lazy val caseSymbols = List(Object_hashCode, Object_toString) ::: productSymbols
+ private lazy val caseValueSymbols = Any_toString :: valueSymbols ::: productSymbols
+ private lazy val caseObjectSymbols = Object_equals :: caseSymbols
+ private def symbolsToSynthesize(clazz: Symbol): List[Symbol] = {
+ if (clazz.isCase) {
+ if (clazz.isDerivedValueClass) caseValueSymbols
+ else if (clazz.isModuleClass) caseSymbols
+ else caseObjectSymbols
+ }
+ else if (clazz.isDerivedValueClass) valueSymbols
+ else Nil
+ }
+
/** Add the synthetic methods to case classes.
*/
def addSyntheticMethods(templ: Template, clazz0: Symbol, context: Context): Template = {
-
- if (phase.erasedTypes)
+ val syntheticsOk = (phase.id <= currentRun.typerPhase.id) && {
+ symbolsToSynthesize(clazz0) filter (_ matchingSymbol clazz0.info isSynthetic) match {
+ case Nil => true
+ case syms => log("Not adding synthetic methods: already has " + syms.mkString(", ")) ; false
+ }
+ }
+ if (!syntheticsOk)
return templ
val synthesizer = new ClassMethodSynthesis(
@@ -94,9 +114,9 @@ trait SyntheticMethods extends ast.TreeDSL {
Apply(gen.mkAttributedRef(method), args.toList)
}
- // Any member, including private
+ // Any concrete member, including private
def hasConcreteImpl(name: Name) =
- clazz.info.member(name).alternatives exists (m => !m.isDeferred && !m.isSynthetic)
+ clazz.info.member(name).alternatives exists (m => !m.isDeferred)
def hasOverridingImplementation(meth: Symbol) = {
val sym = clazz.info nonPrivateMember meth.name
@@ -347,8 +367,7 @@ trait SyntheticMethods extends ast.TreeDSL {
(lb ++= templ.body ++= synthesize()).toList
}
- if (phase.id > currentRun.typerPhase.id) templ
- else deriveTemplate(templ)(body =>
+ deriveTemplate(templ)(body =>
if (clazz.isCase) caseTemplateBody()
else synthesize() match {
case Nil => body // avoiding unnecessary copy