Skip to content

Commit d79b57e

Browse files
authored
Merge pull request #4814 from dotty-staging/fix-4811
Fix #4811: Widen private[this]/protected[this] just before Flatten
2 parents 18fa15e + b156b83 commit d79b57e

File tree

7 files changed

+72
-40
lines changed

7 files changed

+72
-40
lines changed

compiler/src/dotty/tools/dotc/Compiler.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ class Compiler {
6363
new ElimPackagePrefixes) :: // Eliminate references to package prefixes in Select nodes
6464
List(new CheckStatic, // Check restrictions that apply to @static members
6565
new ElimRepeated, // Rewrite vararg parameters and arguments
66-
new NormalizeFlags, // Rewrite some definition flags
6766
new ExpandSAMs, // Expand single abstract method closures to anonymous classes
6867
new ProtectedAccessors, // Add accessors for protected members
6968
new ExtensionMethods, // Expand methods of value classes with extension methods

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ import SymUtils._
3535
*
3636
* Finally, if the constructor of a value class is private pr protected
3737
* it is widened to public.
38+
*
39+
* Also, drop the Local flag from all private[this] and protected[this] members
40+
* that will be moved to the companion object.
3841
*/
3942
class ExtensionMethods extends MiniPhase with DenotTransformer with FullParameterization { thisPhase =>
4043

@@ -46,7 +49,7 @@ class ExtensionMethods extends MiniPhase with DenotTransformer with FullParamete
4649

4750
override def runsAfter = Set(
4851
ElimRepeated.name,
49-
ProtectedAccessors.name // protected accessors cannot handle code that is moved from class to companion object
52+
ProtectedAccessors.name, // protected accessors cannot handle code that is moved from class to companion object
5053
)
5154

5255
override def runsAfterGroupsOf = Set(FirstTransform.name) // need companion objects to exist
@@ -97,17 +100,22 @@ class ExtensionMethods extends MiniPhase with DenotTransformer with FullParamete
97100
moduleClassSym
98101
}
99102
case ref: SymDenotation =>
103+
var ref1 = ref
100104
if (isMethodWithExtension(ref.symbol) && ref.hasAnnotation(defn.TailrecAnnot)) {
101-
val ref1 = ref.copySymDenotation()
105+
ref1 = ref.copySymDenotation()
102106
ref1.removeAnnotation(defn.TailrecAnnot)
103-
ref1
104107
}
105108
else if (ref.isConstructor && isDerivedValueClass(ref.owner) && ref.is(AccessFlags)) {
106-
val ref1 = ref.copySymDenotation()
109+
ref1 = ref.copySymDenotation()
107110
ref1.resetFlag(AccessFlags)
108-
ref1
109111
}
110-
else ref
112+
// Drop the Local flag from all private[this] and protected[this] members
113+
// that will be moved to the companion object.
114+
if (ref.is(Local) && isDerivedValueClass(ref.owner)) {
115+
if (ref1 ne ref) ref1.resetFlag(Local)
116+
else ref1 = ref1.copySymDenotation(initFlags = ref1.flags &~ Local)
117+
}
118+
ref1
111119
case _ =>
112120
ref
113121
}

compiler/src/dotty/tools/dotc/transform/Flatten.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ class Flatten extends MiniPhase with SymTransformer {
1717

1818
override def phaseName = "flatten"
1919

20+
// private[this] and protected[this] modifiers must be dropped
21+
// before classes are lifted. Getters drop these modifiers.
22+
override def runsAfter = Set(Getters.name)
23+
2024
override def changesMembers = true // the phase removes inner classes
2125

2226
private var LiftedDefs: Store.Location[mutable.ListBuffer[Tree]] = _

compiler/src/dotty/tools/dotc/transform/Getters.scala

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,26 +45,38 @@ import ValueClasses._
4545
* --> p.x_=(e)
4646
*
4747
* No fields are generated yet. This is done later in phase Memoize.
48+
*
49+
* Also, drop the Local flag from all private[this] and protected[this] members.
50+
* This allows subsequent code motions in Flatten.
4851
*/
4952
class Getters extends MiniPhase with SymTransformer {
5053
import ast.tpd._
5154

52-
override def phaseName = "getters"
55+
override def phaseName = Getters.name
5356

5457
override def transformSym(d: SymDenotation)(implicit ctx: Context): SymDenotation = {
5558
def noGetterNeeded =
5659
d.is(NoGetterNeeded) ||
57-
d.initial.asInstanceOf[SymDenotation].is(PrivateLocal) && !d.owner.is(Trait) && !isDerivedValueClass(d.owner) && !d.is(Flags.Lazy) ||
60+
d.is(PrivateLocal) && !d.owner.is(Trait) && !isDerivedValueClass(d.owner) && !d.is(Flags.Lazy) ||
5861
d.is(Module) && d.isStatic ||
5962
d.hasAnnotation(defn.ScalaStaticAnnot) ||
6063
d.isSelfSym
61-
if (d.isTerm && (d.is(Lazy) || d.owner.isClass) && d.info.isValueType && !noGetterNeeded) {
62-
val maybeStable = if (d.isStable) Stable else EmptyFlags
63-
d.copySymDenotation(
64-
initFlags = d.flags | maybeStable | AccessorCreationFlags,
65-
info = ExprType(d.info))
64+
65+
var d1 =
66+
if (d.isTerm && (d.is(Lazy) || d.owner.isClass) && d.info.isValueType && !noGetterNeeded) {
67+
val maybeStable = if (d.isStable) Stable else EmptyFlags
68+
d.copySymDenotation(
69+
initFlags = d.flags | maybeStable | AccessorCreationFlags,
70+
info = ExprType(d.info))
71+
}
72+
else d
73+
74+
// Drop the Local flag from all private[this] and protected[this] members.
75+
if (d1.is(Local)) {
76+
if (d1 ne d) d1.resetFlag(Local)
77+
else d1 = d1.copySymDenotation(initFlags = d1.flags &~ Local)
6678
}
67-
else d
79+
d1
6880
}
6981
private val NoGetterNeeded = Method | Param | JavaDefined | JavaStatic
7082

@@ -74,3 +86,7 @@ class Getters extends MiniPhase with SymTransformer {
7486
override def transformAssign(tree: Assign)(implicit ctx: Context): Tree =
7587
if (tree.lhs.symbol is Method) tree.lhs.becomes(tree.rhs).withPos(tree.pos) else tree
7688
}
89+
90+
object Getters {
91+
val name = "getters"
92+
}

compiler/src/dotty/tools/dotc/transform/NormalizeFlags.scala

Lines changed: 0 additions & 25 deletions
This file was deleted.

tests/pos/flatten.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
object A1 {
2+
private[this] class B
3+
4+
private[this] class C {
5+
def cons: B = new B
6+
}
7+
}
8+
9+
class A2 {
10+
private[this] class B
11+
12+
private[this] class C {
13+
def cons: B = new B
14+
}
15+
}

tests/pos/i4811.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
class StringOps(val s: String) extends AnyVal {
2+
def lines: Iterator[String] = new collection.AbstractIterator[String] {
3+
private[this] var index = 0
4+
def hasNext: Boolean = false
5+
def next(): String = {
6+
index = 1
7+
""
8+
}
9+
}
10+
}
11+
12+
class FooOps(val s: String) extends AnyVal {
13+
private[this] def bar = 2
14+
def foo = bar
15+
}

0 commit comments

Comments
 (0)