@@ -48,35 +48,49 @@ object Nullables:
4848 val newHi = if needNullifyHi(lo.typeOpt, hiTpe) then TypeTree (OrType (hiTpe, defn.NullType , soft = false )) else hi
4949 TypeBoundsTree (lo, newHi, alias)
5050
51- /** A set of val or var references that are known to be not null, plus a set of
52- * variable references that are not known (anymore) to be not null
51+ /** A set of val or var references that are known to be not null,
52+ * a set of variable references that are not known (anymore) to be not null,
53+ * plus a set of variables that are known to be not null at any point.
5354 */
54- case class NotNullInfo (asserted : Set [TermRef ], retracted : Set [TermRef ]):
55+ case class NotNullInfo (asserted : Set [TermRef ], retracted : Set [TermRef ], onceRetracted : Set [ TermRef ] ):
5556 assert((asserted & retracted).isEmpty)
57+ assert(retracted.subsetOf(onceRetracted))
5658
5759 def isEmpty = this eq NotNullInfo .empty
5860
59- def retractedInfo = NotNullInfo (Set (), retracted)
61+ def retractedInfo = NotNullInfo (Set (), retracted, onceRetracted)
62+
63+ def onceRetractedInfo = NotNullInfo (Set (), onceRetracted, onceRetracted)
6064
6165 /** The sequential combination with another not-null info */
6266 def seq (that : NotNullInfo ): NotNullInfo =
6367 if this .isEmpty then that
6468 else if that.isEmpty then this
6569 else NotNullInfo (
6670 this .asserted.union(that.asserted).diff(that.retracted),
67- this .retracted.union(that.retracted).diff(that.asserted))
71+ this .retracted.union(that.retracted).diff(that.asserted),
72+ this .onceRetracted.union(that.onceRetracted))
6873
6974 /** The alternative path combination with another not-null info. Used to merge
7075 * the nullability info of the two branches of an if.
7176 */
7277 def alt (that : NotNullInfo ): NotNullInfo =
73- NotNullInfo (this .asserted.intersect(that.asserted), this .retracted.union(that.retracted))
78+ NotNullInfo (
79+ this .asserted.intersect(that.asserted),
80+ this .retracted.union(that.retracted),
81+ this .onceRetracted.union(that.onceRetracted))
82+
83+ def withOnceRetracted (that : NotNullInfo ): NotNullInfo =
84+ if that.isEmpty then this
85+ else NotNullInfo (this .asserted, this .retracted, this .onceRetracted.union(that.onceRetracted))
7486
7587 object NotNullInfo :
76- val empty = new NotNullInfo (Set (), Set ())
88+ val empty = new NotNullInfo (Set (), Set (), Set () )
7789 def apply (asserted : Set [TermRef ], retracted : Set [TermRef ]): NotNullInfo =
78- if asserted.isEmpty && retracted.isEmpty then empty
79- else new NotNullInfo (asserted, retracted)
90+ apply(asserted, retracted, retracted)
91+ def apply (asserted : Set [TermRef ], retracted : Set [TermRef ], onceRetracted : Set [TermRef ]): NotNullInfo =
92+ if asserted.isEmpty && onceRetracted.isEmpty then empty
93+ else new NotNullInfo (asserted, retracted, onceRetracted)
8094 end NotNullInfo
8195
8296 /** A pair of not-null sets, depending on whether a condition is `true` or `false` */
0 commit comments