Skip to content

Commit ae8a246

Browse files
committed
Merge pull request #635 from dotty-staging/fix/private-scala2-trait-setters
Some fixes around mixin and memoization
2 parents 1962ada + 0584e0f commit ae8a246

File tree

9 files changed

+57
-23
lines changed

9 files changed

+57
-23
lines changed

src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,9 @@ class Definitions {
346346
lazy val UncheckedStableAnnot = ctx.requiredClass("scala.annotation.unchecked.uncheckedStable")
347347
lazy val UncheckedVarianceAnnot = ctx.requiredClass("scala.annotation.unchecked.uncheckedVariance")
348348
lazy val VolatileAnnot = ctx.requiredClass("scala.volatile")
349+
lazy val FieldMetaAnnot = ctx.requiredClass("scala.annotation.meta.field")
350+
lazy val GetterMetaAnnot = ctx.requiredClass("scala.annotation.meta.getter")
351+
lazy val SetterMetaAnnot = ctx.requiredClass("scala.annotation.meta.setter")
349352

350353
// convenient one-parameter method types
351354
def methOfAny(tp: Type) = MethodType(List(AnyType), tp)

src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,10 @@ object SymDenotations {
215215
final def transformAnnotations(f: Annotation => Annotation)(implicit ctx: Context): Unit =
216216
annotations = annotations.mapConserve(f)
217217

218+
/** Keep only those annotations that satisfy `p` */
219+
final def filterAnnotations(p: Annotation => Boolean)(implicit ctx: Context): Unit =
220+
annotations = annotations.filterConserve(p)
221+
218222
/** Optionally, the annotation matching the given class symbol */
219223
final def getAnnotation(cls: Symbol)(implicit ctx: Context): Option[Annotation] =
220224
dropOtherAnnotations(annotations, cls) match {
@@ -230,9 +234,9 @@ object SymDenotations {
230234
final def removeAnnotation(cls: Symbol)(implicit ctx: Context): Unit =
231235
annotations = myAnnotations.filterNot(_ matches cls)
232236

233-
/** Copy all annotations from given symbol by adding them to this symbol */
234-
final def addAnnotations(from: Symbol)(implicit ctx: Context): Unit =
235-
from.annotations.foreach(addAnnotation)
237+
/** Add all given annotations to this symbol */
238+
final def addAnnotations(annots: TraversableOnce[Annotation])(implicit ctx: Context): Unit =
239+
annots.foreach(addAnnotation)
236240

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

283287
// ------ Names ----------------------------------------------
284288

289+
/** The expanded name of this denotation. */
290+
final def expandedName(implicit ctx: Context) =
291+
if (is(ExpandedName) || isConstructor) name
292+
else name.expandedName(initial.asSymDenotation.owner)
293+
// need to use initial owner to disambiguate, as multiple private symbols with the same name
294+
// might have been moved from different origins into the same class
295+
285296
/** The name with which the denoting symbol was created */
286297
final def originalName(implicit ctx: Context) = {
287298
val d = initial.asSymDenotation
@@ -1077,11 +1088,7 @@ object SymDenotations {
10771088
def ensureNotPrivate(implicit ctx: Context) =
10781089
if (is(Private))
10791090
copySymDenotation(
1080-
name =
1081-
if (is(ExpandedName) || isConstructor) this.name
1082-
else this.name.expandedName(initial.asSymDenotation.owner),
1083-
// need to use initial owner to disambiguate, as multiple private symbols with the same name
1084-
// might have been moved from different origins into the same class
1091+
name = expandedName,
10851092
initFlags = this.flags &~ Private | ExpandedName)
10861093
else this
10871094
}

src/dotty/tools/dotc/transform/AugmentScala2Traits.scala

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,13 @@ class AugmentScala2Traits extends MiniPhaseTransform with IdentityDenotTransform
6969
info = fullyParameterizedType(mold.info, mixin))
7070
}
7171

72-
def traitSetter(getter: TermSymbol) = {
73-
val separator = if (getter.is(Private)) nme.EXPAND_SEPARATOR else nme.TRAIT_SETTER_SEPARATOR
74-
val expandedGetterName =
75-
if (getter.is(ExpandedName)) getter.name
76-
else getter.name.expandedName(getter.owner, separator)
72+
def traitSetter(getter: TermSymbol) =
7773
getter.copy(
78-
name = expandedGetterName.setterName,
74+
name = getter.ensureNotPrivate.name
75+
.expandedName(getter.owner, nme.TRAIT_SETTER_SEPARATOR)
76+
.asTermName.setterName,
7977
flags = Method | Accessor | ExpandedName,
8078
info = MethodType(getter.info.resultType :: Nil, defn.UnitType))
81-
}
8279

8380
for (sym <- mixin.info.decls) {
8481
if (needsForwarder(sym) || sym.isConstructor || sym.isGetter && sym.is(Lazy))

src/dotty/tools/dotc/transform/ExtensionMethods.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ class ExtensionMethods extends MiniPhaseTransform with DenotTransformer with Ful
117117
imeth.flags | Final &~ (Override | Protected | AbsOverride),
118118
fullyParameterizedType(imeth.info, imeth.owner.asClass),
119119
privateWithin = imeth.privateWithin, coord = imeth.coord)
120-
extensionMeth.addAnnotations(from = imeth)(ctx.withPhase(thisTransformer))
120+
extensionMeth.addAnnotations(imeth.annotations)(ctx.withPhase(thisTransformer))
121121
// need to change phase to add tailrec annotation which gets removed from original method in the same phase.
122122
extensionMeth
123123
}

src/dotty/tools/dotc/transform/Memoize.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,16 @@ import Decorators._
5050
name = sym.name.asTermName.fieldName,
5151
flags = Private | (if (sym is Stable) EmptyFlags else Mutable),
5252
info = sym.info.resultType,
53-
coord = tree.pos).enteredAfter(thisTransform)
53+
coord = tree.pos)
54+
.withAnnotationsCarrying(sym, defn.FieldMetaAnnot)
55+
.enteredAfter(thisTransform)
56+
57+
/** Can be used to filter annotations on getters and setters; not used yet */
58+
def keepAnnotations(denot: SymDenotation, meta: ClassSymbol) = {
59+
val cpy = sym.copySymDenotation()
60+
cpy.filterAnnotations(_.symbol.derivesFrom(meta))
61+
if (cpy.annotations ne denot.annotations) cpy.installAfter(thisTransform)
62+
}
5463

5564
lazy val field = sym.field.orElse(newField).asTerm
5665
if (sym.is(Accessor, butNot = NoFieldNeeded))

src/dotty/tools/dotc/transform/MixinOps.scala

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@ class MixinOps(cls: ClassSymbol, thisTransform: DenotTransformer)(implicit ctx:
1313
val superCls: Symbol = cls.superClass
1414
val mixins: List[ClassSymbol] = cls.mixins
1515

16-
def implementation(member: TermSymbol): TermSymbol =
17-
member.copy(
16+
def implementation(member: TermSymbol): TermSymbol = {
17+
val res = member.copy(
1818
owner = cls,
1919
name = member.name.stripScala2LocalSuffix,
2020
flags = member.flags &~ Deferred,
2121
info = cls.thisType.memberInfo(member)).enteredAfter(thisTransform).asTerm
22+
res.addAnnotations(member.annotations)
23+
res
24+
}
2225

2326
def superRef(target: Symbol, pos: Position = cls.pos): Tree = {
2427
val sup = if (target.isConstructor && !target.owner.is(Trait))

src/dotty/tools/dotc/transform/SymUtils.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import Names._
1111
import StdNames._
1212
import NameOps._
1313
import Flags._
14+
import Annotations._
1415
import language.implicitConversions
1516

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

9192
def implClass(implicit ctx: Context): Symbol =
9293
self.owner.info.decl(self.name.implClassName).symbol
94+
95+
def annotationsCarrying(meta: ClassSymbol)(implicit ctx: Context): List[Annotation] =
96+
self.annotations.filter(_.symbol.hasAnnotation(meta))
97+
98+
def withAnnotationsCarrying(from: Symbol, meta: ClassSymbol)(implicit ctx: Context): self.type = {
99+
self.addAnnotations(from.annotationsCarrying(meta))
100+
self
101+
}
93102
}

tests/pos/scala2traits/dotty-subclass.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
// This is supposed to be compiled by Dotty
22
class Sub extends T
33

4-
class A extends S2T with S2Tprivate {
4+
trait DT {
5+
6+
@volatile lazy val dx = 2
7+
8+
}
9+
10+
class A extends S2T with S2Tprivate with DT {
511
val a: Int = 3
612
var b = 2
713
}

tests/pos/scala2traits/scala-trait.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ trait T {
99
trait S2T {
1010
var x: Int = 0
1111
lazy val y: Int = 1
12-
// val z: Int = 2
12+
val z: Int = 2
1313
val a: Int
1414
var b: Int
1515

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

2424
private def f(x: Int): Int = x + y
2525
def xx = x
2626
def xx_=(x: Int) = this.x = x
2727
def yy = y
28-
// def zz = z
28+
def zz = z
2929
def ff(x: Int) = f(x)
3030
}
3131

0 commit comments

Comments
 (0)