diff options
-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 |