@@ -30,7 +30,24 @@ class Constructors extends MiniPhaseTransform with IdentityDenotTransformer { th
30
30
import tpd ._
31
31
32
32
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 ]()
34
51
35
52
// Collect all private parameter accessors and value definitions that need
36
53
// to be retained. There are several reasons why a parameter accessor or
@@ -40,14 +57,10 @@ class Constructors extends MiniPhaseTransform with IdentityDenotTransformer { th
40
57
// 3. It is accessed on an object other than `this`
41
58
// 4. It is a mutable parameter accessor
42
59
// 5. It is has a wildcard initializer `_`
43
- private val retainedPrivateVals = mutable.Set [Symbol ]()
44
- private val seenPrivateVals = mutable.Set [Symbol ]()
45
-
46
60
private def markUsedPrivateSymbols (tree : RefTree )(implicit ctx : Context ): Unit = {
47
61
48
62
val sym = tree.symbol
49
- def retain () =
50
- retainedPrivateVals.add(sym)
63
+ def retain () = retainedPrivateVals.add(sym)
51
64
52
65
if (sym.exists && sym.owner.isClass && mightBeDropped(sym)) {
53
66
val owner = sym.owner.asClass
@@ -58,7 +71,8 @@ class Constructors extends MiniPhaseTransform with IdentityDenotTransformer { th
58
71
val method = ctx.owner.enclosingMethod
59
72
method.isPrimaryConstructor && ctx.owner.enclosingClass == owner
60
73
}
61
- if (inConstructor && (sym.is(ParamAccessor ) || seenPrivateVals.contains(sym))) {
74
+ if (inConstructor &&
75
+ (sym.is(ParamAccessor ) || seenPrivateVals.contains(sym))) {
62
76
// used inside constructor, accessed on this,
63
77
// could use constructor argument instead, no need to retain field
64
78
}
@@ -79,8 +93,7 @@ class Constructors extends MiniPhaseTransform with IdentityDenotTransformer { th
79
93
}
80
94
81
95
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
84
97
tree
85
98
}
86
99
0 commit comments