Skip to content

Some fixes around mixin and memoization #635

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,9 @@ class Definitions {
lazy val UncheckedStableAnnot = ctx.requiredClass("scala.annotation.unchecked.uncheckedStable")
lazy val UncheckedVarianceAnnot = ctx.requiredClass("scala.annotation.unchecked.uncheckedVariance")
lazy val VolatileAnnot = ctx.requiredClass("scala.volatile")
lazy val FieldMetaAnnot = ctx.requiredClass("scala.annotation.meta.field")
lazy val GetterMetaAnnot = ctx.requiredClass("scala.annotation.meta.getter")
lazy val SetterMetaAnnot = ctx.requiredClass("scala.annotation.meta.setter")

// convenient one-parameter method types
def methOfAny(tp: Type) = MethodType(List(AnyType), tp)
Expand Down
23 changes: 15 additions & 8 deletions src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,10 @@ object SymDenotations {
final def transformAnnotations(f: Annotation => Annotation)(implicit ctx: Context): Unit =
annotations = annotations.mapConserve(f)

/** Keep only those annotations that satisfy `p` */
final def filterAnnotations(p: Annotation => Boolean)(implicit ctx: Context): Unit =
annotations = annotations.filterConserve(p)

/** Optionally, the annotation matching the given class symbol */
final def getAnnotation(cls: Symbol)(implicit ctx: Context): Option[Annotation] =
dropOtherAnnotations(annotations, cls) match {
Expand All @@ -230,9 +234,9 @@ object SymDenotations {
final def removeAnnotation(cls: Symbol)(implicit ctx: Context): Unit =
annotations = myAnnotations.filterNot(_ matches cls)

/** Copy all annotations from given symbol by adding them to this symbol */
final def addAnnotations(from: Symbol)(implicit ctx: Context): Unit =
from.annotations.foreach(addAnnotation)
/** Add all given annotations to this symbol */
final def addAnnotations(annots: TraversableOnce[Annotation])(implicit ctx: Context): Unit =
annots.foreach(addAnnotation)

@tailrec
private def dropOtherAnnotations(anns: List[Annotation], cls: Symbol)(implicit ctx: Context): List[Annotation] = anns match {
Expand Down Expand Up @@ -282,6 +286,13 @@ object SymDenotations {

// ------ Names ----------------------------------------------

/** The expanded name of this denotation. */
final def expandedName(implicit ctx: Context) =
if (is(ExpandedName) || isConstructor) name
else name.expandedName(initial.asSymDenotation.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
Expand Down Expand Up @@ -1077,11 +1088,7 @@ object SymDenotations {
def ensureNotPrivate(implicit ctx: Context) =
if (is(Private))
copySymDenotation(
name =
if (is(ExpandedName) || isConstructor) this.name
else this.name.expandedName(initial.asSymDenotation.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
name = expandedName,
initFlags = this.flags &~ Private | ExpandedName)
else this
}
Expand Down
11 changes: 4 additions & 7 deletions src/dotty/tools/dotc/transform/AugmentScala2Traits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,13 @@ class AugmentScala2Traits extends MiniPhaseTransform with IdentityDenotTransform
info = fullyParameterizedType(mold.info, mixin))
}

def traitSetter(getter: TermSymbol) = {
val separator = if (getter.is(Private)) nme.EXPAND_SEPARATOR else nme.TRAIT_SETTER_SEPARATOR
val expandedGetterName =
if (getter.is(ExpandedName)) getter.name
else getter.name.expandedName(getter.owner, separator)
def traitSetter(getter: TermSymbol) =
getter.copy(
name = expandedGetterName.setterName,
name = getter.ensureNotPrivate.name
.expandedName(getter.owner, nme.TRAIT_SETTER_SEPARATOR)
.asTermName.setterName,
flags = Method | Accessor | ExpandedName,
info = MethodType(getter.info.resultType :: Nil, defn.UnitType))
}

for (sym <- mixin.info.decls) {
if (needsForwarder(sym) || sym.isConstructor || sym.isGetter && sym.is(Lazy))
Expand Down
2 changes: 1 addition & 1 deletion src/dotty/tools/dotc/transform/ExtensionMethods.scala
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful
imeth.flags | Final &~ (Override | Protected | AbsOverride),
fullyParameterizedType(imeth.info, imeth.owner.asClass),
privateWithin = imeth.privateWithin, coord = imeth.coord)
extensionMeth.addAnnotations(from = imeth)(ctx.withPhase(thisTransformer))
extensionMeth.addAnnotations(imeth.annotations)(ctx.withPhase(thisTransformer))
// need to change phase to add tailrec annotation which gets removed from original method in the same phase.
extensionMeth
}
Expand Down
11 changes: 10 additions & 1 deletion src/dotty/tools/dotc/transform/Memoize.scala
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,16 @@ import Decorators._
name = sym.name.asTermName.fieldName,
flags = Private | (if (sym is Stable) EmptyFlags else Mutable),
info = sym.info.resultType,
coord = tree.pos).enteredAfter(thisTransform)
coord = tree.pos)
.withAnnotationsCarrying(sym, defn.FieldMetaAnnot)
.enteredAfter(thisTransform)

/** Can be used to filter annotations on getters and setters; not used yet */
def keepAnnotations(denot: SymDenotation, meta: ClassSymbol) = {
val cpy = sym.copySymDenotation()
cpy.filterAnnotations(_.symbol.derivesFrom(meta))
if (cpy.annotations ne denot.annotations) cpy.installAfter(thisTransform)
}

lazy val field = sym.field.orElse(newField).asTerm
if (sym.is(Accessor, butNot = NoFieldNeeded))
Expand Down
7 changes: 5 additions & 2 deletions src/dotty/tools/dotc/transform/MixinOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,15 @@ class MixinOps(cls: ClassSymbol, thisTransform: DenotTransformer)(implicit ctx:
val superCls: Symbol = cls.superClass
val mixins: List[ClassSymbol] = cls.mixins

def implementation(member: TermSymbol): TermSymbol =
member.copy(
def implementation(member: TermSymbol): TermSymbol = {
val res = member.copy(
owner = cls,
name = member.name.stripScala2LocalSuffix,
flags = member.flags &~ Deferred,
info = cls.thisType.memberInfo(member)).enteredAfter(thisTransform).asTerm
res.addAnnotations(member.annotations)
res
}

def superRef(target: Symbol, pos: Position = cls.pos): Tree = {
val sup = if (target.isConstructor && !target.owner.is(Trait))
Expand Down
9 changes: 9 additions & 0 deletions src/dotty/tools/dotc/transform/SymUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Names._
import StdNames._
import NameOps._
import Flags._
import Annotations._
import language.implicitConversions

object SymUtils {
Expand Down Expand Up @@ -90,4 +91,12 @@ class SymUtils(val self: Symbol) extends AnyVal {

def implClass(implicit ctx: Context): Symbol =
self.owner.info.decl(self.name.implClassName).symbol

def annotationsCarrying(meta: ClassSymbol)(implicit ctx: Context): List[Annotation] =
self.annotations.filter(_.symbol.hasAnnotation(meta))

def withAnnotationsCarrying(from: Symbol, meta: ClassSymbol)(implicit ctx: Context): self.type = {
self.addAnnotations(from.annotationsCarrying(meta))
self
}
}
8 changes: 7 additions & 1 deletion tests/pos/scala2traits/dotty-subclass.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
// This is supposed to be compiled by Dotty
class Sub extends T

class A extends S2T with S2Tprivate {
trait DT {

@volatile lazy val dx = 2

}

class A extends S2T with S2Tprivate with DT {
val a: Int = 3
var b = 2
}
Expand Down
6 changes: 3 additions & 3 deletions tests/pos/scala2traits/scala-trait.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ trait T {
trait S2T {
var x: Int = 0
lazy val y: Int = 1
// val z: Int = 2
val z: Int = 2
val a: Int
var b: Int

Expand All @@ -19,13 +19,13 @@ trait S2T {
trait S2Tprivate {
private var x: Int = 0
private lazy val y: Int = 1
// private val z: Int = 2 // @darkdimius uncomment once lazy vals can be inherited.
private val z: Int = 2

private def f(x: Int): Int = x + y
def xx = x
def xx_=(x: Int) = this.x = x
def yy = y
// def zz = z
def zz = z
def ff(x: Int) = f(x)
}