@@ -45,6 +45,15 @@ class CollectNullableFields extends MiniPhase {
45
45
46
46
override def phaseName = CollectNullableFields .name
47
47
48
+ /** CollectNullableFields records usages of by names */
49
+
50
+ /** Running after `ElimByName` to see by names as nullable types.
51
+ *
52
+ * We don't necessary need to run after `Getters`, but the implementation
53
+ * could be simplified if we were to run before.
54
+ */
55
+ override def runsAfter = Set (Getters .name, ElimByName .name)
56
+
48
57
private [this ] sealed trait FieldInfo
49
58
private [this ] case object NotNullable extends FieldInfo
50
59
private [this ] case class Nullable (by : Symbol ) extends FieldInfo
@@ -53,21 +62,20 @@ class CollectNullableFields extends MiniPhase {
53
62
private [this ] var nullability : IdentityHashMap [Symbol , FieldInfo ] = _
54
63
55
64
override def prepareForUnit (tree : Tree )(implicit ctx : Context ) = {
56
- nullability = new IdentityHashMap
65
+ if (nullability == null ) nullability = new IdentityHashMap
57
66
ctx
58
67
}
59
68
60
69
private def recordUse (tree : Tree )(implicit ctx : Context ): Tree = {
61
- val sym = tree.symbol
70
+ def isField (sym : Symbol ) =
71
+ sym.isField || sym.isGetter // running after phase Getters
62
72
63
- def isNullableType (tpe : Type ) =
64
- tpe.isInstanceOf [ExprType ] ||
65
- tpe.widenDealias.typeSymbol.isNullableClass
73
+ val sym = tree.symbol
66
74
val isNullablePrivateField =
67
- sym. isField &&
75
+ isField(sym) &&
68
76
sym.is(Private , butNot = Lazy ) &&
69
77
! sym.owner.is(Trait ) &&
70
- isNullableType( sym.info)
78
+ sym.info.widenDealias.typeSymbol.isNullableClass
71
79
72
80
if (isNullablePrivateField)
73
81
nullability.get(sym) match {
@@ -76,8 +84,8 @@ class CollectNullableFields extends MiniPhase {
76
84
case null => // not in the map
77
85
val from = ctx.owner
78
86
val isNullable =
79
- from.is(Lazy ) && from. isField && // used in lazy field initializer
80
- from.owner.eq(sym.owner) // lazy val and field in the same class
87
+ from.is(Lazy ) && isField(from) && // used in lazy field initializer
88
+ from.owner.eq(sym.owner) // lazy val and field defined in the same class
81
89
val info = if (isNullable) Nullable (from) else NotNullable
82
90
nullability.put(sym, info)
83
91
case _ =>
@@ -96,16 +104,16 @@ class CollectNullableFields extends MiniPhase {
96
104
recordUse(tree)
97
105
98
106
/** Map lazy values to the fields they should null after initialization. */
99
- def lazyValNullables (implicit ctx : Context ): Map [Symbol , List [Symbol ]] = {
100
- val result = new mutable. HashMap [Symbol , mutable.ListBuffer [Symbol ]]
107
+ def lazyValNullables (implicit ctx : Context ): IdentityHashMap [Symbol , mutable. ListBuffer [Symbol ]] = {
108
+ val result = new IdentityHashMap [Symbol , mutable.ListBuffer [Symbol ]]
101
109
102
110
nullability.forEach {
103
111
case (sym, Nullable (from)) =>
104
- val bldr = result.getOrElseUpdate (from, new mutable.ListBuffer )
112
+ val bldr = result.computeIfAbsent (from, _ => new mutable.ListBuffer )
105
113
bldr += sym
106
114
case _ =>
107
115
}
108
116
109
- result.mapValues(_.toList).toMap
117
+ result
110
118
}
111
119
}
0 commit comments