From 4e0e48a5fd1e05a29860490ab89a1539c50fd50d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 23 Mar 2015 18:34:24 +0100 Subject: [PATCH] New attempt to fix the leaking companion problem We now invalidate for all lifted symbols, whether they come form a tree or not. --- src/dotty/tools/dotc/transform/Flatten.scala | 30 ++++++++++++++++++- .../tools/dotc/transform/RestoreScopes.scala | 17 ----------- 2 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/dotty/tools/dotc/transform/Flatten.scala b/src/dotty/tools/dotc/transform/Flatten.scala index 0bd1bb75fdd4..66552ba5500e 100644 --- a/src/dotty/tools/dotc/transform/Flatten.scala +++ b/src/dotty/tools/dotc/transform/Flatten.scala @@ -5,6 +5,10 @@ import core._ import DenotTransformers.SymTransformer import Phases.Phase import Contexts.Context +import Symbols._ +import Names.Name +import NameOps._ +import typer.Mode import Flags._ import SymUtils._ import SymDenotations.SymDenotation @@ -16,11 +20,35 @@ class Flatten extends MiniPhaseTransform with SymTransformer { thisTransform => import ast.tpd._ override def phaseName = "flatten" + /** Mark absent any companion classes or objects of the flattened version of `cls` + * in package `pkg` which are not yet completed. These are inner classes entered + * into the package scope by reading their class files. They should never be read + * because their information is superseded by the lifted class info. + */ + private def invalidateUndefinedCompanions(pkg: ClassSymbol, cls: ClassSymbol)(implicit ctx: Context): Unit = { + def invalidate(otherName: Name) = { + val other = pkg.info.decl(otherName).asSymDenotation + if (other.exists && !other.isCompleted) other.markAbsent + } + if (cls is Flags.Module) { + invalidate(cls.name.sourceModuleName) + invalidate(cls.name.stripModuleClassSuffix.toTypeName) + } + else { + invalidate(cls.name.toTermName) + invalidate(cls.name.moduleClassName) + } + } + def transformSym(ref: SymDenotation)(implicit ctx: Context) = { if (ref.isClass && !ref.is(Package) && !ref.owner.is(Package)) { + val cls = ref.symbol.asClass + val pkg = ref.enclosingPackageClass.asClass + invalidateUndefinedCompanions(pkg, cls)( + ctx.withPhase(cls.initial.validFor.phaseId).addMode(Mode.FutureDefsOK)) ref.copySymDenotation( name = ref.flatName(), - owner = ref.enclosingPackageClass) + owner = pkg) } else ref } diff --git a/src/dotty/tools/dotc/transform/RestoreScopes.scala b/src/dotty/tools/dotc/transform/RestoreScopes.scala index 7c84e8749fa7..01894b11f86e 100644 --- a/src/dotty/tools/dotc/transform/RestoreScopes.scala +++ b/src/dotty/tools/dotc/transform/RestoreScopes.scala @@ -6,12 +6,9 @@ import DenotTransformers.IdentityDenotTransformer import Contexts.Context import Symbols._ import Scopes._ -import collection.mutable import TreeTransforms.MiniPhaseTransform import SymDenotations._ import ast.Trees._ -import NameOps._ -import typer.Mode import TreeTransforms.TransformerInfo /** The preceding lambda lift and flatten phases move symbols to different scopes @@ -22,18 +19,6 @@ class RestoreScopes extends MiniPhaseTransform with IdentityDenotTransformer { t import ast.tpd._ override def phaseName = "restoreScopes" - private def invalidateUndefinedCompanions(pkg: ClassSymbol, cls: ClassSymbol)(implicit ctx: Context): Unit = { - val otherNames = - if (cls is Flags.Module) - List(cls.name.sourceModuleName, cls.name.stripModuleClassSuffix.toTypeName) - else - List(cls.name.toTermName, cls.name.moduleClassName) - for (otherName <- otherNames) { - val other = pkg.info.decl(otherName).asSymDenotation - if (other.exists && !other.isCompleted) other.markAbsent - } - } - override def transformTypeDef(tree: TypeDef)(implicit ctx: Context, info: TransformerInfo) = { val TypeDef(_, impl: Template) = tree // @@ -46,8 +31,6 @@ class RestoreScopes extends MiniPhaseTransform with IdentityDenotTransformer { t val cls = tree.symbol.asClass val pkg = cls.owner.asClass pkg.enter(cls) - invalidateUndefinedCompanions(pkg, cls)( - ctx.withPhase(cls.initial.validFor.phaseId).addMode(Mode.FutureDefsOK)) val cinfo = cls.classInfo tree.symbol.copySymDenotation( info = cinfo.derivedClassInfo( // Dotty deviation: Cannot expand cinfo inline without a type error