diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2016-11-10 16:43:42 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-11-10 16:43:42 +1000 |
commit | e0a0d3d974429531ef2d5283b8468ff8d8290f09 (patch) | |
tree | 82f40828237621028c17eaef5e27a21aeb3fb41a | |
parent | 9ca14a56fc4fb84ef6e760ce75e45f21352d3a18 (diff) | |
parent | 4959e9f11c459e1c1eaa6cc168a4b9f2e784ffdf (diff) | |
download | scala-e0a0d3d974429531ef2d5283b8468ff8d8290f09.tar.gz scala-e0a0d3d974429531ef2d5283b8468ff8d8290f09.tar.bz2 scala-e0a0d3d974429531ef2d5283b8468ff8d8290f09.zip |
Merge pull request #5486 from som-snytt/issue/6734-synths
SI-6734 Synthesize companion near case class
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 21 | ||||
-rw-r--r-- | test/files/pos/t6734.scala | 17 |
2 files changed, 35 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 7d48c548a1..cca6f280e3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3139,10 +3139,25 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val initElems = scope.elems // SI-5877 The decls of a package include decls of the package object. But we don't want to add // the corresponding synthetics to the package class, only to the package object class. - def shouldAdd(sym: Symbol) = - inBlock || !context.isInPackageObject(sym, context.owner) + // SI-6734 Locality test below is meaningless if we're not even in the correct tree. + // For modules that are synthetic case companions, check that case class is defined here. + def shouldAdd(sym: Symbol): Boolean = { + def shouldAddAsModule: Boolean = + sym.moduleClass.attachments.get[ClassForCaseCompanionAttachment] match { + case Some(att) => + val cdef = att.caseClass + stats.exists { + case t @ ClassDef(_, _, _, _) => t.symbol == cdef.symbol // cdef ne t + case _ => false + } + case _ => true + } + + (!sym.isModule || shouldAddAsModule) && (inBlock || !context.isInPackageObject(sym, context.owner)) + } for (sym <- scope) - for (tree <- context.unit.synthetics get sym if shouldAdd(sym)) { // OPT: shouldAdd is usually true. Call it here, rather than in the outer loop + // OPT: shouldAdd is usually true. Call it here, rather than in the outer loop + for (tree <- context.unit.synthetics.get(sym) if shouldAdd(sym)) { newStats += typedStat(tree) // might add even more synthetics to the scope context.unit.synthetics -= sym } diff --git a/test/files/pos/t6734.scala b/test/files/pos/t6734.scala new file mode 100644 index 0000000000..88932cd2cc --- /dev/null +++ b/test/files/pos/t6734.scala @@ -0,0 +1,17 @@ + +// desugars to package p { object `package` } +// previously, synthetic p.C was incorrectly added to this tree +// This only matters because synthetics are not hygienic +package object p + +package p { + import scala.concurrent.Future + case class C private[p] (value: Future[Int]) // private to avoid rewriting C.apply to new C +} + +package client { + trait X { + import scala.concurrent.Future + def f = p.C(Future(42)(null)) // ensure synthetics were generated, i.e., p.C.apply + } +} |