@@ -45,6 +45,15 @@ class CollectNullableFields extends MiniPhase {
4545
4646 override def phaseName = CollectNullableFields .name
4747
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+
4857 private [this ] sealed trait FieldInfo
4958 private [this ] case object NotNullable extends FieldInfo
5059 private [this ] case class Nullable (by : Symbol ) extends FieldInfo
@@ -53,21 +62,20 @@ class CollectNullableFields extends MiniPhase {
5362 private [this ] var nullability : IdentityHashMap [Symbol , FieldInfo ] = _
5463
5564 override def prepareForUnit (tree : Tree )(implicit ctx : Context ) = {
56- nullability = new IdentityHashMap
65+ if (nullability == null ) nullability = new IdentityHashMap
5766 ctx
5867 }
5968
6069 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
6272
63- def isNullableType (tpe : Type ) =
64- tpe.isInstanceOf [ExprType ] ||
65- tpe.widenDealias.typeSymbol.isNullableClass
73+ val sym = tree.symbol
6674 val isNullablePrivateField =
67- sym. isField &&
75+ isField(sym) &&
6876 sym.is(Private , butNot = Lazy ) &&
6977 ! sym.owner.is(Trait ) &&
70- isNullableType( sym.info)
78+ sym.info.widenDealias.typeSymbol.isNullableClass
7179
7280 if (isNullablePrivateField)
7381 nullability.get(sym) match {
@@ -76,8 +84,8 @@ class CollectNullableFields extends MiniPhase {
7684 case null => // not in the map
7785 val from = ctx.owner
7886 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
8189 val info = if (isNullable) Nullable (from) else NotNullable
8290 nullability.put(sym, info)
8391 case _ =>
@@ -96,16 +104,16 @@ class CollectNullableFields extends MiniPhase {
96104 recordUse(tree)
97105
98106 /** 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 ]]
101109
102110 nullability.forEach {
103111 case (sym, Nullable (from)) =>
104- val bldr = result.getOrElseUpdate (from, new mutable.ListBuffer )
112+ val bldr = result.computeIfAbsent (from, _ => new mutable.ListBuffer )
105113 bldr += sym
106114 case _ =>
107115 }
108116
109- result.mapValues(_.toList).toMap
117+ result
110118 }
111119}
0 commit comments