Skip to content

Commit c20d6e7

Browse files
committed
Address review and add docs
1 parent 10561f1 commit c20d6e7

File tree

3 files changed

+32
-12
lines changed

3 files changed

+32
-12
lines changed

compiler/src/dotty/tools/dotc/transform/init/Checking.scala

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import Effects._, Potentials._, Summary._, Util._
2020
object Checking {
2121
/** The checking state
2222
*
23-
* Why `visited` is a set of `MethodCall` instead of `Symbol`? Think the following program:
23+
* Why `visited` is a set of effects instead of `Symbol`? Think the following program:
2424
*
2525
* class C(x: Int, a: A @cold) {
2626
* val n = if (x > 0) new C(x - 1, a).m() else 0
@@ -84,22 +84,17 @@ object Checking {
8484
val (pots, effs) = Summarization.analyze(vdef.rhs)(theEnv.withOwner(vdef.symbol))
8585
theEnv.summaryOf(cls).cacheFor(vdef.symbol, (pots, effs))
8686
if (!vdef.symbol.is(Flags.Lazy)) {
87-
checkEffects(effs)
87+
checkEffectsIn(effs, cls)
8888
traceIndented(vdef.symbol.show + " initialized", init)
8989
state.fieldsInited += vdef.symbol
9090
}
9191

9292
case tree =>
9393
val (_, effs) = Summarization.analyze(tree)
94-
checkEffects(effs)
94+
checkEffectsIn(effs, cls)
9595
}
9696
}
9797

98-
def checkEffects(effs: Effects): Unit = {
99-
val rebased = Effects.asSeenFrom(effs, ThisRef(state.thisClass)(null), cls, Potentials.empty)
100-
rebased.foreach { check(_) }
101-
}
102-
10398
// check parent calls : follows linearization ordering
10499
// see spec 5.1 about "Template Evaluation".
105100
// https://www.scala-lang.org/files/archive/spec/2.13/05-classes-and-objects.html
@@ -159,8 +154,7 @@ object Checking {
159154

160155
(stats :+ expr).foreach { stat =>
161156
val (_, effs) = Summarization.analyze(stat)(theEnv.withOwner(ctor))
162-
val rebased = Effects.asSeenFrom(effs, ThisRef(state.thisClass)(null), cls, Potentials.empty)
163-
rebased.foreach { check(_) }
157+
checkEffectsIn(effs, cls)
164158
}
165159
}
166160

@@ -183,6 +177,11 @@ object Checking {
183177
source.sourcePos
184178
)
185179

180+
private def checkEffectsIn(effs: Effects, cls: ClassSymbol)(implicit state: State): Unit = {
181+
val rebased = Effects.asSeenFrom(effs, ThisRef(state.thisClass)(null), cls, Potentials.empty)
182+
rebased.foreach { check(_) }
183+
}
184+
186185
private def check(eff: Effect)(implicit state: State): Unit =
187186
if (!state.visited.contains(eff)) traceOp("checking effect " + eff.show, init) {
188187
implicit val state2: State = state.withVisited(eff)
@@ -317,8 +316,8 @@ object Checking {
317316
}
318317
}
319318

320-
private def expand(pot: Potential)(implicit state: State): Potentials =
321-
trace("expand " + pot.show, init, pots => Potentials.show(pots.asInstanceOf[Potentials])) { pot match {
319+
private def expand(pot: Potential)(implicit state: State): Potentials = trace("expand " + pot.show, init, pots => Potentials.show(pots.asInstanceOf[Potentials])) {
320+
pot match {
322321
case MethodReturn(pot1, sym) =>
323322
pot1 match {
324323
case thisRef @ ThisRef(cls) =>

compiler/src/dotty/tools/dotc/transform/init/Effects.scala

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,38 @@ object Effects {
1818
def show(effs: Effects)(implicit ctx: Context): String =
1919
effs.map(_.show).mkString(", ")
2020

21+
/** Effects that are related to safe initialization */
2122
sealed trait Effect {
2223
def size: Int
2324
def show(implicit ctx: Context): String
2425
def source: Tree
2526
}
2627

28+
/** An effect means that a value that's possibly under initialization
29+
* leaks from the initializing world to fully-initialized world.
30+
*
31+
* Essentially, this effect enforces that the object pointed to by
32+
* `potential` is fully initialized.
33+
*
34+
* This effect is trigger in several scenarios:
35+
* - a potential is used as arguments to method calls or new-expressions
36+
* - a potential is assigned (not initialize) to a field
37+
* - the selection chain on a potential is too long
38+
*/
2739
case class Leak(potential: Potential)(val source: Tree) extends Effect {
2840
def size: Int = potential.size
2941
def show(implicit ctx: Context): String =
3042
potential.show + ""
3143
}
3244

45+
/** Field access, `a.f` */
3346
case class FieldAccess(potential: Potential, field: Symbol)(val source: Tree) extends Effect {
3447
def size: Int = potential.size
3548
def show(implicit ctx: Context): String =
3649
potential.show + "." + field.name.show + "!"
3750
}
3851

52+
/** Method call, `a.m()` */
3953
case class MethodCall(potential: Potential, method: Symbol)(val source: Tree) extends Effect {
4054
def size: Int = potential.size
4155
def show(implicit ctx: Context): String = potential.show + "." + method.name.show + "!"

compiler/src/dotty/tools/dotc/transform/init/Potentials.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ object Potentials {
2020
def show(pots: Potentials)(implicit ctx: Context): String =
2121
pots.map(_.show).mkString(", ")
2222

23+
/** A potential represents an aliasing of a value that is possibly under initialization */
2324
sealed trait Potential {
2425
def size: Int
2526
def show(implicit ctx: Context): String
2627
def source: Tree
2728
}
2829

30+
/** The object pointed by `C.this` */
2931
case class ThisRef(classSymbol: ClassSymbol)(val source: Tree) extends Potential {
3032
val size: Int = 1
3133
def show(implicit ctx: Context): String = classSymbol.name.show + ".this"
@@ -50,6 +52,7 @@ object Potentials {
5052
}
5153
}
5254

55+
/** The object pointed by `C.super.this`, mainly used for override resolution */
5356
case class SuperRef(pot: Potential, supercls: ClassSymbol)(val source: Tree) extends Potential {
5457
val size: Int = 1
5558
def show(implicit ctx: Context): String = pot.show + ".super[" + supercls.name.show + "]"
@@ -113,21 +116,25 @@ object Potentials {
113116
def show(implicit ctx: Context): String = "Outer[" + pot.show + ", " + classSymbol.show + "]"
114117
}
115118

119+
/** The object pointed by `this.f` */
116120
case class FieldReturn(potential: Potential, field: Symbol)(val source: Tree) extends Potential {
117121
def size: Int = potential.size + 1
118122
def show(implicit ctx: Context): String = potential.show + "." + field.name.show
119123
}
120124

125+
/** The object returned by `this.m()` */
121126
case class MethodReturn(potential: Potential, symbol: Symbol)(val source: Tree) extends Potential {
122127
def size: Int = potential.size + 1
123128
def show(implicit ctx: Context): String = potential.show + "." + symbol.name.show
124129
}
125130

131+
/** The object whose initialization status is unknown */
126132
case class Cold()(val source: Tree) extends Potential {
127133
def size: Int = 1
128134
def show(implicit ctx: Context): String = "Cold"
129135
}
130136

137+
/** A function when called will produce the `effects` and return the `potentials` */
131138
case class Fun(potentials: Potentials, effects: Effects)(val source: Tree) extends Potential {
132139
def size: Int = 1
133140
def show(implicit ctx: Context): String =

0 commit comments

Comments
 (0)