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