@@ -149,17 +149,26 @@ class Constructors extends MiniPhase with IdentityDenotTransformer { thisPhase =
149149 // (2) If the parameter accessor reference was to an alias getter,
150150 // drop the () when replacing by the parameter.
151151 object intoConstr extends TreeMap {
152- private var isSuperCall = false
152+ private var inSuperCall = false
153153 override def transform (tree : Tree )(using Context ): Tree = tree match {
154154 case Ident (_) | Select (This (_), _) =>
155155 var sym = tree.symbol
156- if sym.is(ParamAccessor ) && (! sym.is(Mutable ) || isSuperCall)
157- // Variables need to go through the getter since they might have been updated,
158- // except if we are in a super call, since then the virtual getter call would
159- // be illegal.
160- then
156+ def isOverridableSelect = tree.isInstanceOf [Select ] && ! sym.isEffectivelyFinal
157+ def switchOutsideSupercall = ! sym.is(Mutable ) && ! isOverridableSelect
158+ // If true, switch to constructor parameters also in the constructor body
159+ // that follows the super call.
160+ // Variables need to go through the getter since they might have been updated.
161+ // References via this need to use the getter as well as long as that getter
162+ // can be overridden. This is needed to handle overrides correctly. See run/i15723.scala.
163+ // Note that in a supercall we need to switch to parameters in any case since then
164+ // calling the virtual getter call would be illegal.
165+ //
166+ // Note: We intentionally treat references via this and identifiers differently
167+ // here. Identifiers in a constructor always bind to the parameter. This is
168+ // done for backwards compatbility.
169+ if sym.is(ParamAccessor ) && (switchOutsideSupercall || inSuperCall) then
161170 sym = sym.subst(accessors, paramSyms)
162- if ( sym.maybeOwner.isConstructor) ref(sym).withSpan(tree.span) else tree
171+ if sym.maybeOwner.isConstructor then ref(sym).withSpan(tree.span) else tree
163172 case Apply (fn, Nil ) =>
164173 val fn1 = transform(fn)
165174 if ((fn1 ne fn) && fn1.symbol.is(Param ) && fn1.symbol.owner.isPrimaryConstructor)
@@ -170,7 +179,7 @@ class Constructors extends MiniPhase with IdentityDenotTransformer { thisPhase =
170179 }
171180
172181 def apply (tree : Tree , prevOwner : Symbol )(using Context ): Tree =
173- isSuperCall = isSuperConstrCall(tree)
182+ inSuperCall = isSuperConstrCall(tree)
174183 transform(tree).changeOwnerAfter(prevOwner, constr.symbol, thisPhase)
175184 }
176185
0 commit comments