From 07ea487704abe8969efcbb6672ce63a1748bbd73 Mon Sep 17 00:00:00 2001 From: Dmitry Petrashko Date: Wed, 24 Aug 2016 13:39:52 +0200 Subject: [PATCH 1/4] Fix handling of superCalls. 1. There may be calls to super on non-this. 2. there may be calls to in-dirrect super-traits. --- src/dotty/tools/backend/jvm/CollectSuperCalls.scala | 7 +++++-- src/dotty/tools/backend/jvm/DottyBackendInterface.scala | 6 +++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/dotty/tools/backend/jvm/CollectSuperCalls.scala b/src/dotty/tools/backend/jvm/CollectSuperCalls.scala index 8f9b067ba7ac..e504047f3fb9 100644 --- a/src/dotty/tools/backend/jvm/CollectSuperCalls.scala +++ b/src/dotty/tools/backend/jvm/CollectSuperCalls.scala @@ -20,8 +20,11 @@ class CollectSuperCalls extends MiniPhaseTransform { override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree = { tree.qualifier match { - case Super(qual: This, mix) if mix.nonEmpty => - val classSymbol = qual.symbol.asClass.classSymbol + case Super(qual, mix) if mix.nonEmpty => + val classSymbol: ClassSymbol = qual match { + case qual: This => qual.symbol.asClass.classSymbol + case qual => qual.symbol.info.classSymbol.asClass + } registerSuperCall(classSymbol, tree.symbol.owner.asClass) case _ => } diff --git a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala index 30934605bd21..34bcd0757cef 100644 --- a/src/dotty/tools/backend/jvm/DottyBackendInterface.scala +++ b/src/dotty/tools/backend/jvm/DottyBackendInterface.scala @@ -747,9 +747,13 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma */ def superInterfaces: List[Symbol] = { val directlyInheritedTraits = decorateSymbol(sym).directlyInheritedTraits + val directlyInheritedTraitsSet = directlyInheritedTraits.toSet val allBaseClasses = directlyInheritedTraits.iterator.flatMap(_.symbol.asClass.baseClasses.drop(1)).toSet val superCalls = superCallsMap.getOrElse(sym, Set.empty) - directlyInheritedTraits.filter(t => !allBaseClasses(t) || superCalls(t)) + val additional = (superCalls -- directlyInheritedTraitsSet).filter(_.is(Flags.Trait)) +// if (additional.nonEmpty) +// println(s"$fullName: adding supertraits $additional") + directlyInheritedTraits.filter(t => !allBaseClasses(t) || superCalls(t)) ++ additional } /** From 75358be7265a067e603bd95d422ca8edc0bdaeb7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 25 Aug 2016 16:52:55 +0200 Subject: [PATCH 2/4] Fix select static Need to do time travel to find out whether members were created as static symbols. After LambdaLift and Flatten most symbols are static anyway. --- .../tools/dotc/core/SymDenotations.scala | 29 +++++++++++-------- .../tools/dotc/transform/SelectStatic.scala | 24 +++++++-------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 47ec541ab84c..be2e3d8fe22d 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -46,7 +46,7 @@ trait SymDenotations { this: Context => val initial = denot.initial val firstPhaseId = initial.validFor.firstPhaseId.max(ctx.typerPhase.id) if ((initial ne denot) || ctx.phaseId != firstPhaseId) - ctx.withPhase(firstPhaseId).stillValidInOwner(initial.asSymDenotation) + ctx.withPhase(firstPhaseId).stillValidInOwner(initial) else stillValidInOwner(denot) } @@ -77,7 +77,7 @@ trait SymDenotations { this: Context => implicit val ctx: Context = this val initial = denot.initial if ((initial ne denot) || ctx.phaseId != initial.validFor.firstPhaseId) { - ctx.withPhase(initial.validFor.firstPhaseId).traceInvalid(initial.asSymDenotation) + ctx.withPhase(initial.validFor.firstPhaseId).traceInvalid(initial) } else try { val owner = denot.owner.denot if (!traceInvalid(owner)) explainSym("owner is invalid") @@ -346,14 +346,14 @@ object SymDenotations { else { def legalize(name: Name): Name = // JVM method names may not contain `<' or `>' characters if (is(Method)) name.replace('<', '(').replace('>', ')') else name - legalize(name.expandedName(initial.asSymDenotation.owner)) + legalize(name.expandedName(initial.owner)) } // need to use initial owner to disambiguate, as multiple private symbols with the same name // might have been moved from different origins into the same class /** The name with which the denoting symbol was created */ final def originalName(implicit ctx: Context) = { - val d = initial.asSymDenotation + val d = initial if (d is ExpandedName) d.name.unexpandedName else d.name // !!!DEBUG, was: effectiveName } @@ -435,13 +435,13 @@ object SymDenotations { /** Is this symbol an anonymous class? */ final def isAnonymousClass(implicit ctx: Context): Boolean = - isClass && (initial.asSymDenotation.name startsWith tpnme.ANON_CLASS) + isClass && (initial.name startsWith tpnme.ANON_CLASS) final def isAnonymousFunction(implicit ctx: Context) = - this.symbol.is(Method) && (initial.asSymDenotation.name startsWith nme.ANON_FUN) + this.symbol.is(Method) && (initial.name startsWith nme.ANON_FUN) final def isAnonymousModuleVal(implicit ctx: Context) = - this.symbol.is(ModuleVal) && (initial.asSymDenotation.name startsWith nme.ANON_CLASS) + this.symbol.is(ModuleVal) && (initial.name startsWith nme.ANON_CLASS) /** Is this a companion class method or companion object method? * These methods are generated by Symbols#synthesizeCompanionMethod @@ -606,7 +606,7 @@ object SymDenotations { /** Is this symbol a class that extends `AnyVal`? */ final def isValueClass(implicit ctx: Context): Boolean = { - val di = this.initial.asSymDenotation + val di = initial di.isClass && di.derivesFrom(defn.AnyValClass)(ctx.withPhase(di.validFor.firstPhaseId)) // We call derivesFrom at the initial phase both because AnyVal does not exist @@ -1164,6 +1164,8 @@ object SymDenotations { d } + override def initial: SymDenotation = super.initial.asSymDenotation + /** Install this denotation as the result of the given denotation transformer. */ override def installAfter(phase: DenotTransformer)(implicit ctx: Context): Unit = super.installAfter(phase) @@ -1226,10 +1228,13 @@ object SymDenotations { if (myTypeParams == null) myTypeParams = if (ctx.erasedTypes || is(Module)) Nil // fast return for modules to avoid scanning package decls - else if (this ne initial) initial.asSymDenotation.typeParams - else infoOrCompleter match { - case info: TypeParamsCompleter => info.completerTypeParams(symbol) - case _ => typeParamsFromDecls + else { + val di = initial + if (this ne di) di.typeParams + else infoOrCompleter match { + case info: TypeParamsCompleter => info.completerTypeParams(symbol) + case _ => typeParamsFromDecls + } } myTypeParams } diff --git a/src/dotty/tools/dotc/transform/SelectStatic.scala b/src/dotty/tools/dotc/transform/SelectStatic.scala index 504a66c2f26d..5d60bb984102 100644 --- a/src/dotty/tools/dotc/transform/SelectStatic.scala +++ b/src/dotty/tools/dotc/transform/SelectStatic.scala @@ -19,25 +19,21 @@ class SelectStatic extends MiniPhaseTransform with IdentityDenotTransformer { th import ast.tpd._ override def phaseName: String = "selectStatic" - private val isPackage = FlagConjunction(PackageCreationFlags.bits) override def transformSelect(tree: tpd.Select)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { val sym = tree.symbol - val r1 = - if (!sym.is(isPackage) && !sym.maybeOwner.is(isPackage) && - ( - ((sym is Flags.Module) && sym.maybeOwner.isStaticOwner) || - (sym is Flags.JavaStatic) || - (sym.maybeOwner is Flags.ImplClass) || - sym.hasAnnotation(ctx.definitions.ScalaStaticAnnot) - ) - ) - if (!tree.qualifier.symbol.is(JavaModule) && !tree.qualifier.isType) - Block(List(tree.qualifier), ref(sym)) - else tree + def isStaticMember = + (sym is Flags.Module) && sym.initial.maybeOwner.initial.isStaticOwner || + (sym is Flags.JavaStatic) || + (sym.maybeOwner is Flags.ImplClass) || + sym.hasAnnotation(ctx.definitions.ScalaStaticAnnot) + val isStaticRef = !sym.is(Package) && !sym.maybeOwner.is(Package) && isStaticMember + val tree1 = + if (isStaticRef && !tree.qualifier.symbol.is(JavaModule) && !tree.qualifier.isType) + Block(List(tree.qualifier), ref(sym)) else tree - normalize(r1) + normalize(tree1) } private def normalize(t: Tree)(implicit ctx: Context) = t match { From 7062b90eec9f63aef9023401ea8ca0acd524e0d6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 25 Aug 2016 16:56:06 +0200 Subject: [PATCH 3/4] Avoid stale symbol errors for Scala-2 compiled symbols Wehn compiling dotty repeatedly using dotc.Bench, we got a stale symbol error involving an outer field of a Scala class. These can always be assumed to be current, as we would not think to recompile Scala2 classes mixed with dotty classes in the same session (we'd need two concurrent compilers for that). --- src/dotty/tools/dotc/core/SymDenotations.scala | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index be2e3d8fe22d..bedfb672fa37 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -56,6 +56,7 @@ trait SymDenotations { this: Context => stillValid(owner) && ( !owner.isClass || owner.isRefinementClass + || owner.is(Scala2x) || (owner.unforcedDecls.lookupAll(denot.name) contains denot.symbol) || denot.isSelfSym) } catch { From c9d670f4ce41662215799a728b145c6a2f6ab826 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 21 Sep 2016 19:15:27 +0200 Subject: [PATCH 4/4] Fix CollectSuper Add comment what it is supposed to achieve and change the implementation to follow the comment. --- .../tools/backend/jvm/CollectSuperCalls.scala | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/dotty/tools/backend/jvm/CollectSuperCalls.scala b/src/dotty/tools/backend/jvm/CollectSuperCalls.scala index e504047f3fb9..8285bfe4b5e9 100644 --- a/src/dotty/tools/backend/jvm/CollectSuperCalls.scala +++ b/src/dotty/tools/backend/jvm/CollectSuperCalls.scala @@ -4,9 +4,13 @@ import dotty.tools.dotc.ast.tpd import dotty.tools.dotc.ast.Trees._ import dotty.tools.dotc.core.Contexts.Context import dotty.tools.dotc.core.Symbols._ +import dotty.tools.dotc.core.Flags.Trait import dotty.tools.dotc.transform.TreeTransforms.{MiniPhaseTransform, TransformerInfo} -/** Collect all super calls except to the parent class. +/** Collect all super calls to trait members. + * + * For each super reference to trait member, register a call from the current class to the + * owner of the referenced member. * * This information is used to know if it is safe to remove a redundant mixin class. * A redundant mixin class is one that is implemented by another mixin class. As the @@ -20,12 +24,9 @@ class CollectSuperCalls extends MiniPhaseTransform { override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree = { tree.qualifier match { - case Super(qual, mix) if mix.nonEmpty => - val classSymbol: ClassSymbol = qual match { - case qual: This => qual.symbol.asClass.classSymbol - case qual => qual.symbol.info.classSymbol.asClass - } - registerSuperCall(classSymbol, tree.symbol.owner.asClass) + case sup: Super => + if (tree.symbol.owner.is(Trait)) + registerSuperCall(ctx.owner.enclosingClass.asClass, tree.symbol.owner.asClass) case _ => } tree