Skip to content

Commit

Permalink
Generate super accessor for traits
Browse files Browse the repository at this point in the history
  • Loading branch information
liufengyun committed Jul 15, 2020
1 parent 8dd35ac commit 37fac7f
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 16 deletions.
12 changes: 11 additions & 1 deletion compiler/src/dotty/tools/dotc/transform/ResolveSuper.scala
Expand Up @@ -9,6 +9,8 @@ import SymUtils._
import Symbols._
import Decorators._
import DenotTransformers._
import Names._
import StdNames._
import NameOps._
import NameKinds._
import ResolveSuper._
Expand Down Expand Up @@ -80,10 +82,18 @@ object ResolveSuper {
def rebindSuper(base: Symbol, acc: Symbol)(using Context): Symbol = {
var bcs = base.info.baseClasses.dropWhile(acc.owner != _).tail
var sym: Symbol = NoSymbol
val SuperAccessorName(memberName) = acc.name.unexpandedName
var mix: Name = nme.EMPTY
val memberName = acc.name.unexpandedName match
case SuperAccessorName(ExpandPrefixName(name, mixName)) =>
mix = mixName.toTypeName
name
case SuperAccessorName(name) =>
name

ctx.debuglog(i"starting rebindsuper from $base of ${acc.showLocated}: ${acc.info} in $bcs, name = $memberName")
while (bcs.nonEmpty && sym == NoSymbol) {
val other = bcs.head.info.nonPrivateDecl(memberName)
.filterWithPredicate(denot => denot.exists && (mix.isEmpty || denot.symbol.owner.name == mix))
.matchingDenotation(base.thisType, base.thisType.memberInfo(acc))
ctx.debuglog(i"rebindsuper ${bcs.head} $other deferred = ${other.symbol.is(Deferred)}")
if other.exists && !other.symbol.is(Deferred) then
Expand Down
20 changes: 8 additions & 12 deletions compiler/src/dotty/tools/dotc/transform/SuperAccessors.scala
Expand Up @@ -5,13 +5,13 @@ import dotty.tools.dotc.ast.{Trees, tpd}
import scala.collection.mutable
import ValueClasses.isMethodWithExtension
import core._
import Contexts._, Flags._, Symbols._, NameOps._, Trees._, Types.SuperType
import Contexts._, Flags._, Symbols._, Names._, StdNames._, NameOps._, Trees._
import TypeUtils._, SymUtils._
import DenotTransformers.DenotTransformer
import Symbols._
import util.Spans._
import Decorators._
import NameKinds.SuperAccessorName
import NameKinds.{ SuperAccessorName, ExpandPrefixName }

/** This class adds super accessors for all super calls that either
* appear in a trait or have as a target a member of some outer class.
Expand Down Expand Up @@ -62,11 +62,12 @@ class SuperAccessors(thisPhase: DenotTransformer) {
private val accDefs = newMutableSymbolMap[mutable.ListBuffer[Tree]]

/** A super accessor call corresponding to `sel` */
private def superAccessorCall(sel: Select)(using Context) = {
private def superAccessorCall(sel: Select, mixName: Name = nme.EMPTY)(using Context) = {
val Select(qual, name) = sel
val sym = sel.symbol
val clazz = qual.symbol.asClass
var superName = SuperAccessorName(name.asTermName)
val preName = if (mixName.isEmpty) name.toTermName else ExpandPrefixName(name.toTermName, mixName.toTermName)
var superName = SuperAccessorName(preName)
if (clazz.is(Trait)) superName = superName.expandedName(clazz)
val superInfo = sel.tpe.widenSingleton.ensureMethodic

Expand Down Expand Up @@ -147,19 +148,14 @@ class SuperAccessors(thisPhase: DenotTransformer) {
}
}

def mixIsTrait = sup.tpe match {
case SuperType(thisTpe, superTpe) => superTpe.typeSymbol.is(Trait)
}

val needAccessor = name.isTermName && {
mix.name.isEmpty && (clazz.is(Trait) || clazz != currentClass || !validCurrentClass) ||
// SI-8803. If we access super[A] from an inner class (!= currentClass) or closure (validCurrentClass),
// where A is the superclass we need an accessor. If A is a parent trait we don't: in this case mixin
// will re-route the super call directly to the impl class (it's statically known).
!mix.name.isEmpty && (clazz != currentClass || !validCurrentClass) && !mixIsTrait
// where A is the superclass we need an accessor.
!mix.name.isEmpty && (clazz != currentClass || !validCurrentClass)
}

if (needAccessor) atPhase(thisPhase.next)(superAccessorCall(sel))
if (needAccessor) atPhase(thisPhase.next)(superAccessorCall(sel, mix.name))
else sel
}

Expand Down
6 changes: 3 additions & 3 deletions tests/run/t10290.scala
Expand Up @@ -21,8 +21,8 @@ object Test {
def main(args : Array[String]) : Unit = {
val b = new B
val c = new b.C
assert(c.t1 == "A1")
assert(c.t2 == "A2")
assert(c.t3 == "B")
assert(c.t1 == "A1", c.t1)
assert(c.t2 == "A2", c.t2)
assert(c.t3 == "B", c.t3)
}
}

0 comments on commit 37fac7f

Please sign in to comment.