@@ -10,6 +10,10 @@ import Symbols._
1010import MegaPhase ._
1111import Flags ._
1212import 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
90121object Getters {
0 commit comments