Skip to content

Commit c8c7520

Browse files
committed
Don't generate setters for private fields in desugar
The reason is that some of these fields might be converted later to private[this] fields which do not get setter. Instead, generate setters for private vars that are not private[this] in phase Getters.
1 parent dacfba8 commit c8c7520

File tree

2 files changed

+36
-5
lines changed

2 files changed

+36
-5
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ object desugar {
155155
val vdef @ ValDef(name, tpt, rhs) = transformQuotedPatternName(vdef0)
156156
val mods = vdef.mods
157157
val setterNeeded =
158-
mods.is(Mutable) && ctx.owner.isClass && (!mods.isAllOf(PrivateLocal) || ctx.owner.is(Trait))
158+
mods.is(Mutable) && ctx.owner.isClass && (!mods.is(Private) || ctx.owner.is(Trait))
159159
if (setterNeeded) {
160160
// TODO: copy of vdef as getter needed?
161161
// val getter = ValDef(mods, name, tpt, rhs) withPos vdef.pos?

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

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import Symbols._
1010
import MegaPhase._
1111
import Flags._
1212
import ValueClasses._
13+
import SymUtils._
14+
import NameOps._
15+
import collection.mutable
16+
1317

1418
/** Performs the following rewritings for fields of a class:
1519
*
@@ -30,13 +34,20 @@ import ValueClasses._
3034
* <mods> non-static <module> val x$ = e
3135
* --> <mods> <module> <accessor> def x$ = e
3236
*
37+
* Also, generate setters for fields that are private but not private[this]
38+
* The form of a setter is
39+
*
40+
* <mods> def x_=(init: T): Unit = ()
41+
*
3342
* Omitted from the rewritings are
3443
*
3544
* - private[this] fields in classes (excluding traits, value classes)
3645
* - fields generated for static modules (TODO: needed?)
3746
* - parameters, static fields, and fields coming from Java
3847
*
39-
* Furthermore, assignments to mutable vars are replaced by setter calls
48+
* The rhs is computed later, in phase Memoize.
49+
*
50+
* Furthermore, assignments to mutable vars with setters are replaced by setter calls
4051
*
4152
* p.x = e
4253
* --> p.x_=(e)
@@ -46,7 +57,7 @@ import ValueClasses._
4657
* Also, drop the Local flag from all private[this] and protected[this] members.
4758
* This allows subsequent code motions in Flatten.
4859
*/
49-
class Getters extends MiniPhase with SymTransformer {
60+
class Getters extends MiniPhase with SymTransformer { thisPhase =>
5061
import ast.tpd._
5162

5263
override def phaseName: String = Getters.name
@@ -80,11 +91,31 @@ class Getters extends MiniPhase with SymTransformer {
8091
}
8192
private val NoGetterNeededFlags = Method | Param | JavaDefined | JavaStatic
8293

94+
val newSetters = mutable.HashSet[Symbol]()
95+
96+
def ensureSetter(sym: TermSymbol)(given Context) =
97+
if !sym.setter.exists then
98+
newSetters += sym.copy(
99+
name = sym.name.setterName,
100+
info = MethodType(sym.info.widenExpr :: Nil, defn.UnitType)
101+
).enteredAfter(thisPhase)
102+
83103
override def transformValDef(tree: ValDef)(implicit ctx: Context): Tree =
84-
if (tree.symbol.is(Method)) DefDef(tree.symbol.asTerm, tree.rhs).withSpan(tree.span) else tree
104+
val sym = tree.symbol
105+
if !sym.is(Method) then return tree
106+
val getterDef = DefDef(sym.asTerm, tree.rhs).withSpan(tree.span)
107+
if !sym.is(Mutable) then return getterDef
108+
ensureSetter(sym.asTerm)
109+
if !newSetters.contains(sym.setter) then return getterDef
110+
val setterDef = DefDef(sym.setter.asTerm, unitLiteral)
111+
Thicket(getterDef, setterDef)
85112

86113
override def transformAssign(tree: Assign)(implicit ctx: Context): Tree =
87-
if (tree.lhs.symbol.is(Method)) tree.lhs.becomes(tree.rhs).withSpan(tree.span) else tree
114+
val lsym = tree.lhs.symbol.asTerm
115+
if (lsym.is(Method))
116+
ensureSetter(lsym)
117+
tree.lhs.becomes(tree.rhs).withSpan(tree.span)
118+
else tree
88119
}
89120

90121
object Getters {

0 commit comments

Comments
 (0)