@@ -52,35 +52,49 @@ object Nullables:
5252 val hiTree = if (hiTpe eq hi.typeOpt) hi else TypeTree (hiTpe)
5353 TypeBoundsTree (lo, hiTree, alias)
5454
55- /** A set of val or var references that are known to be not null, plus a set of
56- * variable references that are not known (anymore) to be not null
55+ /** A set of val or var references that are known to be not null,
56+ * a set of variable references that are not known (anymore) to be not null,
57+ * plus a set of variables that are known to be not null at any point.
5758 */
58- case class NotNullInfo (asserted : Set [TermRef ], retracted : Set [TermRef ]):
59+ case class NotNullInfo (asserted : Set [TermRef ], retracted : Set [TermRef ], onceRetracted : Set [ TermRef ] ):
5960 assert((asserted & retracted).isEmpty)
61+ assert(retracted.subsetOf(onceRetracted))
6062
6163 def isEmpty = this eq NotNullInfo .empty
6264
63- def retractedInfo = NotNullInfo (Set (), retracted)
65+ def retractedInfo = NotNullInfo (Set (), retracted, onceRetracted)
66+
67+ def onceRetractedInfo = NotNullInfo (Set (), onceRetracted, onceRetracted)
6468
6569 /** The sequential combination with another not-null info */
6670 def seq (that : NotNullInfo ): NotNullInfo =
6771 if this .isEmpty then that
6872 else if that.isEmpty then this
6973 else NotNullInfo (
7074 this .asserted.union(that.asserted).diff(that.retracted),
71- this .retracted.union(that.retracted).diff(that.asserted))
75+ this .retracted.union(that.retracted).diff(that.asserted),
76+ this .onceRetracted.union(that.onceRetracted))
7277
7378 /** The alternative path combination with another not-null info. Used to merge
7479 * the nullability info of the two branches of an if.
7580 */
7681 def alt (that : NotNullInfo ): NotNullInfo =
77- NotNullInfo (this .asserted.intersect(that.asserted), this .retracted.union(that.retracted))
82+ NotNullInfo (
83+ this .asserted.intersect(that.asserted),
84+ this .retracted.union(that.retracted),
85+ this .onceRetracted.union(that.onceRetracted))
86+
87+ def withOnceRetracted (that : NotNullInfo ): NotNullInfo =
88+ if that.isEmpty then this
89+ else NotNullInfo (this .asserted, this .retracted, this .onceRetracted.union(that.onceRetracted))
7890
7991 object NotNullInfo :
80- val empty = new NotNullInfo (Set (), Set ())
92+ val empty = new NotNullInfo (Set (), Set (), Set () )
8193 def apply (asserted : Set [TermRef ], retracted : Set [TermRef ]): NotNullInfo =
82- if asserted.isEmpty && retracted.isEmpty then empty
83- else new NotNullInfo (asserted, retracted)
94+ apply(asserted, retracted, retracted)
95+ def apply (asserted : Set [TermRef ], retracted : Set [TermRef ], onceRetracted : Set [TermRef ]): NotNullInfo =
96+ if asserted.isEmpty && onceRetracted.isEmpty then empty
97+ else new NotNullInfo (asserted, retracted, onceRetracted)
8498 end NotNullInfo
8599
86100 /** A pair of not-null sets, depending on whether a condition is `true` or `false` */
0 commit comments