@@ -14,19 +14,41 @@ import symtab.Flags._
14
14
*
15
15
* For traits:
16
16
*
17
- * - Namers translates a definition `val x = rhs` into a getter `def x = rhs`
17
+ * - Namers translates a definition `val x = rhs` into a getter `def x = rhs` -- no underlying field is created.
18
18
* - This phase moves `rhs` into a block nested under the template's local dummy.
19
19
* If the value is memoized (stored), the block's final expression assigns the value to the val,
20
20
* and the val itself is left without a rhs.
21
- * (Dotty uses a method `x$compute` instead of a block, which is used in the constructor to initialize the val.
22
- * It also unifies strict and lazy vals, in that the RHS is lifted to a method for both.)
23
- * If the value of the rhs is a literal or unit, it is not stored and the final expression of the block is ().
24
- * The val then retains this statically known value as its rhs, with its side-effects still lifted to the block.
25
- * - This phases also synthesizes accessors and fields for any vals mixed into a non-trait class.
26
- * - Constructors moves the expressions in the template into the constructor,
27
- * which means it will initialize the values defined in this template.
21
+ * If the value of the rhs is a literal (ConstantType), it is not stored and the final expression of the block is ().
22
+ * The val then retains this statically known value as its rhs.
23
+ * (We could extend this to other fields that needn't be stored,
24
+ * but would still need to lift their side-effects to the block.
25
+ * We're mostly to set up for this, and experimented with doing this for Unit-typed vals.
26
+ * No longer storing and writing to fields is too much of a a change in semantics.
27
+ * Mainly regarding the memory model -- visibility of writes across threads etc would change.)
28
+ * - This phase also synthesizes accessors and fields for any vals mixed into a non-trait class.
29
+ * - Constructors moves the statements in the template into the constructor,
30
+ * which means it will initialize the fields defined in this template (and execute the corresponding side effects).
28
31
*
29
- * Runs before erasure (to get bridges), but before lambdalift/flatten, so nested functions/definitions must be considered.
32
+ * Runs before erasure (to get bridges), and thus before lambdalift/flatten, so that nested functions/definitions must be considered.
33
+ *
34
+ * TODO:
35
+ * - remove backwards compatibility hacks to complete migration to Java 8-encoding of traits
36
+ * - minimize introduction of new flag bits?
37
+ * - ...
38
+ *
39
+ * In the future, would like to get closer to dotty, which lifts a val's RHS to a method `x$compute` instead of a block,
40
+ * which is used in the constructor to initialize the val.
41
+ * This makes for a nice unification of strict and lazy vals,in that the RHS is lifted to a method for both,
42
+ * with the corresponding compute method called at the appropriate time.)
43
+ *
44
+ * In the even longer term, I agree with @DarkDimius that it would make sense to
45
+ * hide the difference between strict and lazy vals. All vals are lazy,
46
+ * but the memoization overhead is removed when we statically know they are forced during initialiation.
47
+ * We could still expose the low-level field semantics through `private[this] val`s.
48
+ *
49
+ * In any case, the current behavior of overriding vals is pretty surprising.
50
+ * An overridden val's side-effect is still performed.
51
+ * The only change due to overriding is that its value is never written to the field (the overridden val's value is, of course).
30
52
*/
31
53
abstract class Fields extends InfoTransform with ast.TreeDSL with TypingTransformers {
32
54
0 commit comments