@@ -30,7 +30,24 @@ class Constructors extends MiniPhaseTransform with IdentityDenotTransformer { th
3030 import tpd ._
3131
3232 override def phaseName : String = " constructors"
33- override def runsAfter : Set [Class [_ <: Phase ]] = Set (classOf [Memoize ], classOf [HoistSuperArgs ])
33+ override def runsAfter : Set [Class [_ <: Phase ]] = Set (classOf [HoistSuperArgs ])
34+ override def runsAfterGroupsOf : Set [Class [_ <: Phase ]] = Set (classOf [Memoize ])
35+ // Memoized needs to be finished because we depend on the ownerchain after Memoize
36+ // when checking whether an ident is an access in a constructor or outside it.
37+ // This test is done in the right-hand side of a value definition. If Memoize
38+ // was in the same group as Constructors, the test on the rhs ident would be
39+ // performed before the rhs undergoes the owner change. This would lead
40+ // to more symbls being retained as parameters. Test case is
41+ //
42+ // dotc tests/pos/captuing.scala -Xprint:constr
43+ //
44+ // `sf` should not be retained as a filed of class `MT`.
45+
46+ /** The private vals that are known to be retained as class fields */
47+ private val retainedPrivateVals = mutable.Set [Symbol ]()
48+
49+ /** The private vals whose definition comes before the current focus */
50+ private val seenPrivateVals = mutable.Set [Symbol ]()
3451
3552 // Collect all private parameter accessors and value definitions that need
3653 // to be retained. There are several reasons why a parameter accessor or
@@ -40,14 +57,10 @@ class Constructors extends MiniPhaseTransform with IdentityDenotTransformer { th
4057 // 3. It is accessed on an object other than `this`
4158 // 4. It is a mutable parameter accessor
4259 // 5. It is has a wildcard initializer `_`
43- private val retainedPrivateVals = mutable.Set [Symbol ]()
44- private val seenPrivateVals = mutable.Set [Symbol ]()
45-
4660 private def markUsedPrivateSymbols (tree : RefTree )(implicit ctx : Context ): Unit = {
4761
4862 val sym = tree.symbol
49- def retain () =
50- retainedPrivateVals.add(sym)
63+ def retain () = retainedPrivateVals.add(sym)
5164
5265 if (sym.exists && sym.owner.isClass && mightBeDropped(sym)) {
5366 val owner = sym.owner.asClass
@@ -58,7 +71,8 @@ class Constructors extends MiniPhaseTransform with IdentityDenotTransformer { th
5871 val method = ctx.owner.enclosingMethod
5972 method.isPrimaryConstructor && ctx.owner.enclosingClass == owner
6073 }
61- if (inConstructor && (sym.is(ParamAccessor ) || seenPrivateVals.contains(sym))) {
74+ if (inConstructor &&
75+ (sym.is(ParamAccessor ) || seenPrivateVals.contains(sym))) {
6276 // used inside constructor, accessed on this,
6377 // could use constructor argument instead, no need to retain field
6478 }
@@ -79,8 +93,7 @@ class Constructors extends MiniPhaseTransform with IdentityDenotTransformer { th
7993 }
8094
8195 override def transformValDef (tree : tpd.ValDef )(implicit ctx : Context , info : TransformerInfo ): tpd.Tree = {
82- if (mightBeDropped(tree.symbol))
83- (if (isWildcardStarArg(tree.rhs)) retainedPrivateVals else seenPrivateVals) += tree.symbol
96+ if (mightBeDropped(tree.symbol)) seenPrivateVals += tree.symbol
8497 tree
8598 }
8699
0 commit comments