@@ -70,11 +70,22 @@ import Decorators._
70
70
lazy val field = sym.field.orElse(newField).asTerm
71
71
if (sym.is(Accessor , butNot = NoFieldNeeded ))
72
72
if (sym.isGetter) {
73
- var rhs = tree.rhs.changeOwnerAfter(sym, field, thisTransform)
74
- if (isWildcardArg(rhs)) rhs = EmptyTree
75
- val fieldDef = transformFollowing(ValDef (field, rhs))
76
- val getterDef = cpy.DefDef (tree)(rhs = transformFollowingDeep(ref(field)))
77
- Thicket (fieldDef, getterDef)
73
+ def skipBlocks (t : Tree ): Tree = t match {
74
+ case Block (a, b) if a.forall(isIdempotentExpr) => skipBlocks(b)
75
+ case _ => t
76
+ }
77
+ if (sym.is(Flags .Final ) && skipBlocks(tree.rhs).isInstanceOf [Literal ])
78
+ // duplicating scalac behavior: for final vals that have rhs as constant, we do not create a field
79
+ // and instead return the value. This seemingly minor optimization has huge effect on initialization
80
+ // order and the values that can be observed during superconstructor call
81
+ tree
82
+ else {
83
+ var rhs = tree.rhs.changeOwnerAfter(sym, field, thisTransform)
84
+ if (isWildcardArg(rhs)) rhs = EmptyTree
85
+ val fieldDef = transformFollowing(ValDef (field, rhs))
86
+ val getterDef = cpy.DefDef (tree)(rhs = transformFollowingDeep(ref(field)))
87
+ Thicket (fieldDef, getterDef)
88
+ }
78
89
}
79
90
else if (sym.isSetter) {
80
91
if (! sym.is(ParamAccessor )) { val Literal (Constant (())) = tree.rhs } // this is intended as an assertion
0 commit comments