diff options
author | Paul Phillips <paulp@improving.org> | 2012-10-23 09:34:50 -0700 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2012-10-30 14:04:45 -0700 |
commit | 6740ba7832410baee77afd8189e4f8977a866a2b (patch) | |
tree | 44a30797455b3bf6187f3420bbb99c3429d32048 /src | |
parent | 2c554249fd8e99286134b217027b6e3cb2c92d77 (diff) | |
download | scala-6740ba7832410baee77afd8189e4f8977a866a2b.tar.gz scala-6740ba7832410baee77afd8189e4f8977a866a2b.tar.bz2 scala-6740ba7832410baee77afd8189e4f8977a866a2b.zip |
SI-6578 Harden against synthetics being added more than once.
Don't add synthetic methods if they already contain synthetic
methods from the set we're about to add.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala | 31 |
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 |