From 61f1f4dddb8e760d628cdeeb88c579f1ef0fb2a9 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Wed, 15 Apr 2015 20:27:24 +0200 Subject: [PATCH 1/7] Companion methods should have Method flag. --- src/dotty/tools/dotc/core/Symbols.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index dab84bb5f69c..47342cb56d33 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -161,12 +161,14 @@ trait Symbols { this: Context => owner.thisType, modcls, parents, decls, TermRef.withSymAndName(owner.thisType, module, name)), privateWithin, coord, assocFile) + val companionMethodFlags = Flags.Synthetic | Flags.Private | Flags.Method + def synthesizeCompanionMethod(name: Name, target: SymDenotation, owner: SymDenotation)(implicit ctx: Context) = if (owner.exists && target.exists && !owner.isAbsent && !target.isAbsent) { val existing = owner.unforcedDecls.lookup(name) existing.orElse{ - ctx.newSymbol(owner.symbol, name, Flags.Synthetic | Flags.Private, ExprType(target.typeRef)) + ctx.newSymbol(owner.symbol, name, companionMethodFlags , ExprType(target.typeRef)) } } else NoSymbol From bd9e18f2b2c8f0550fc0daab5473d9f6856cc329 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Wed, 15 Apr 2015 20:46:52 +0200 Subject: [PATCH 2/7] Ycheck that companions do not disappear. --- src/dotty/tools/dotc/transform/TreeChecker.scala | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala index 43e1ce8a6853..d415cbce41a0 100644 --- a/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -56,6 +56,16 @@ class TreeChecker extends Phase with SymTransformer { registry(name) = sym } + def checkCompanion(symd: SymDenotation)(implicit ctx: Context): Unit = { + val cur = symd.linkedClass + val prev = ctx.atPhase(ctx.phase.prev) { + implicit ctx => + symd.symbol.linkedClass + } + + if (prev.exists) + assert(cur.exists, i"companion disappeared from $symd") + } def transformSym(symd: SymDenotation)(implicit ctx: Context): SymDenotation = { val sym = symd.symbol @@ -69,6 +79,8 @@ class TreeChecker extends Phase with SymTransformer { testDuplicate(sym, seenClasses, "class") } + checkCompanion(symd) + symd } From 3c9fb037658e5b9ff5775ca34edbf1e228d91685 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Wed, 15 Apr 2015 20:47:30 +0200 Subject: [PATCH 3/7] Fix RestoreScopes from destroying companion links. Fixes #476 --- src/dotty/tools/dotc/transform/RestoreScopes.scala | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/dotty/tools/dotc/transform/RestoreScopes.scala b/src/dotty/tools/dotc/transform/RestoreScopes.scala index 3a168b1fe52d..fe24186acc90 100644 --- a/src/dotty/tools/dotc/transform/RestoreScopes.scala +++ b/src/dotty/tools/dotc/transform/RestoreScopes.scala @@ -13,6 +13,7 @@ import ast.Trees._ import NameOps._ import typer.Mode import TreeTransforms.TransformerInfo +import StdNames._ /** The preceding lambda lift and flatten phases move symbols to different scopes * and rename them. This miniphase cleans up afterwards and makes sure that all @@ -33,6 +34,19 @@ class RestoreScopes extends MiniPhaseTransform with IdentityDenotTransformer { t // For top-level classes this does nothing. val cls = tree.symbol.asClass val pkg = cls.owner.asClass + + // Bring back companion links + val companionClass = cls.info.decls.lookup(nme.COMPANION_CLASS_METHOD) + val companionModule = cls.info.decls.lookup(nme.COMPANION_MODULE_METHOD) + + if (companionClass.exists) { + restoredDecls.enter(companionClass) + } + + if (companionModule.exists) { + restoredDecls.enter(companionModule) + } + pkg.enter(cls) val cinfo = cls.classInfo tree.symbol.copySymDenotation( From 1ce894e06a3a7b3ca64e62c1de515c2125e89343 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Wed, 15 Apr 2015 21:55:35 +0200 Subject: [PATCH 4/7] Disable checking of presence of companion objects: forces to much. Triggers cycles in ExtensionMethods. --- src/dotty/tools/dotc/transform/TreeChecker.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala index d415cbce41a0..ba790d377321 100644 --- a/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -79,7 +79,9 @@ class TreeChecker extends Phase with SymTransformer { testDuplicate(sym, seenClasses, "class") } - checkCompanion(symd) + + // checkCompanion(symd) // disabled as it forces to much in presence of companion objects. + // left in code as it could help reveal errors in some cases symd } From e74587fae00c1ca61934f3387f9bcfb6b0ddc6d2 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Thu, 16 Apr 2015 10:37:48 +0200 Subject: [PATCH 5/7] Companion_Module method is not a method with extension. --- src/dotty/tools/dotc/transform/ValueClasses.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/transform/ValueClasses.scala b/src/dotty/tools/dotc/transform/ValueClasses.scala index ab4bba94ea53..a7a0db97c5d3 100644 --- a/src/dotty/tools/dotc/transform/ValueClasses.scala +++ b/src/dotty/tools/dotc/transform/ValueClasses.scala @@ -7,6 +7,7 @@ import Symbols._ import SymDenotations._ import Contexts._ import Flags._ +import StdNames._ /** Methods that apply to user-defined value classes */ object ValueClasses { @@ -22,7 +23,8 @@ object ValueClasses { isDerivedValueClass(d.owner) && !d.isConstructor && !d.is(SuperAccessor) && - !d.is(Macro) + !d.is(Macro) && + !(d.name eq nme.COMPANION_MODULE_METHOD) /** The member that of a derived value class that unboxes it. */ def valueClassUnbox(d: ClassDenotation)(implicit ctx: Context): Symbol = From 31c56ee54e16e94016a0f46579863eef1f19efc6 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Thu, 16 Apr 2015 10:37:54 +0200 Subject: [PATCH 6/7] Revert "Disable checking of presence of companion objects: forces to much." The problem was due to cycles in ExtensionMethod themselves. This reverts commit 1ce894e06a3a7b3ca64e62c1de515c2125e89343. --- src/dotty/tools/dotc/transform/TreeChecker.scala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala index ba790d377321..d415cbce41a0 100644 --- a/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -79,9 +79,7 @@ class TreeChecker extends Phase with SymTransformer { testDuplicate(sym, seenClasses, "class") } - - // checkCompanion(symd) // disabled as it forces to much in presence of companion objects. - // left in code as it could help reveal errors in some cases + checkCompanion(symd) symd } From 4efca0f2e6d8fb91cd68da09809fe8165011aab3 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Thu, 16 Apr 2015 15:50:08 +0200 Subject: [PATCH 7/7] Make checkCompanion stable against future Defs --- src/dotty/tools/dotc/transform/TreeChecker.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dotty/tools/dotc/transform/TreeChecker.scala b/src/dotty/tools/dotc/transform/TreeChecker.scala index d415cbce41a0..1661f7576a55 100644 --- a/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -59,8 +59,10 @@ class TreeChecker extends Phase with SymTransformer { def checkCompanion(symd: SymDenotation)(implicit ctx: Context): Unit = { val cur = symd.linkedClass val prev = ctx.atPhase(ctx.phase.prev) { - implicit ctx => + ct => { + implicit val ctx: Context = ct.withMode(Mode.FutureDefsOK) symd.symbol.linkedClass + } } if (prev.exists)