Skip to content

Commit 10561f1

Browse files
committed
Make doc align with paper
1 parent d15fe8f commit 10561f1

File tree

1 file changed

+39
-31
lines changed

1 file changed

+39
-31
lines changed

docs/docs/reference/other-new-features/safe-initialization.md

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ The checker will report:
3333
| ^
3434
| Access non-initialized field value localFile. Calling trace:
3535
| -> val extension: String = name.substring(4) [ AbstractFile.scala:3 ]
36-
| -> def name: String = localFile [ AbstractFile.scala:8 ]
36+
| -> def name: String = localFile [ AbstractFile.scala:8 ]
3737
```
3838

3939
### Inner-Outer Interaction
@@ -56,9 +56,9 @@ The checker will report:
5656
5 | private var counter = 0 // error
5757
| ^
5858
| Access non-initialized field variable counter. Calling trace:
59-
| -> val theEmptyValDef = new EmptyValDef [ trees.scala:4 ]
60-
| -> class EmptyValDef extends ValDef [ trees.scala:3 ]
61-
| -> class ValDef { counter += 1 } [ trees.scala:2 ]
59+
| -> val theEmptyValDef = new EmptyValDef [ trees.scala:4 ]
60+
| -> class EmptyValDef extends ValDef [ trees.scala:3 ]
61+
| -> class ValDef { counter += 1 } [ trees.scala:2 ]
6262
```
6363

6464
### Functions
@@ -84,9 +84,9 @@ The checker reports:
8484
7 | val b = "hello" // error
8585
| ^
8686
|Access non-initialized field value b. Calling trace:
87-
| -> val a = f() [ features-high-order.scala:6 ]
87+
| -> val a = f() [ features-high-order.scala:6 ]
8888
| -> val f: () => String = () => this.message [ features-high-order.scala:2 ]
89-
| -> def message: String = b [ features-high-order.scala:8 ]
89+
| -> def message: String = b [ features-high-order.scala:8 ]
9090
```
9191

9292
## Design Goals
@@ -114,14 +114,34 @@ _stackability_, _monotonicity_ and _scopability_.
114114

115115
Stackability means that objects are initialized in stack order: if the
116116
object `b` is created during the initialization of object `a`, then
117-
`b` should become transitively initialized before or at the same time as `a`.
118-
Scala enforces this property in syntax, except for the language
119-
feature below:
117+
`b` should become transitively initialized before or at the same time
118+
as `a`. Scala enforces this property in syntax by demanding that all
119+
fields are initialized at the end of the primary constructor, except
120+
for the language feature below:
120121

121122
``` scala
122123
var x: T = _
123124
```
124125

126+
Control effects such as exceptions may break this property, as the
127+
following example shows:
128+
129+
``` scala
130+
class MyException(val b: B) extends Exception("")
131+
class A {
132+
val b = try { new B } catch { case myEx: MyException => myEx.b }
133+
println(b.a)
134+
}
135+
class B {
136+
throw new MyException(this)
137+
val a: Int = 1
138+
}
139+
```
140+
141+
In the code above, the control effect teleport the uninitialized value
142+
wrapped in an exception. In the implementation, we avoid the problem
143+
by ensuring that the values that are thrown must be transitively initialized.
144+
125145
Monotonicity means that the initialization status of an object should
126146
not go backward: initialized fields continue to be initialized, a
127147
field points to an initialized object may not later point to an
@@ -146,28 +166,16 @@ typestate_ to ensure soundness in the presence of aliasing
146166
[1]. Otherwise, either soundness will be compromised or we have to
147167
disallow the usage of already initialized fields.
148168

149-
Scopability means that given any environment ρ (which are the value
150-
bindings for method parameters) for evaluating an expression `e`, the
151-
resulting value is either transitively initialized or it may only
152-
reach uninitialized objects that are reachable from ρ in the heap
153-
before the evaluation. Control effects such as exceptions break this
154-
property, as the following example shows:
155-
156-
``` scala
157-
class MyException(val b: B) extends Exception("")
158-
class A {
159-
val b = try { new B } catch { case myEx: MyException => myEx.b }
160-
println(b.a)
161-
}
162-
class B {
163-
throw new MyException(this)
164-
val a: Int = 1
165-
}
166-
```
167-
168-
In the code above, the control effect teleport the uninitialized value
169-
wrapped in an exception. In the implementation, we avoid the problem
170-
by ensuring that the values that are thrown must be transitively initialized.
169+
Scopability means that given any environment `ρ` (which are the value
170+
bindings for method parameters) and heap `σ` for evaluating an
171+
expression `e`, if the resulting value reaches an object `o`
172+
pre-existent in `σ`, then `o` is reachable from `ρ` in `σ`. Control
173+
effects like coroutines, delimited control, resumable exceptions may
174+
break the property, as they can transport a value upper in the stack
175+
(not in scope) to be reachable from the current scope. Static fields
176+
can also serve as a teleport thus breaks this property. In the
177+
implementation, we need to enforce that teleported values are
178+
transitively initialized.
171179

172180
With the established principles and design goals, following rules are imposed:
173181

0 commit comments

Comments
 (0)