@@ -52,35 +52,49 @@ object Nullables:
52
52
val hiTree = if (hiTpe eq hi.typeOpt) hi else TypeTree (hiTpe)
53
53
TypeBoundsTree (lo, hiTree, alias)
54
54
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.
57
58
*/
58
- case class NotNullInfo (asserted : Set [TermRef ], retracted : Set [TermRef ]):
59
+ case class NotNullInfo (asserted : Set [TermRef ], retracted : Set [TermRef ], onceRetracted : Set [ TermRef ] ):
59
60
assert((asserted & retracted).isEmpty)
61
+ assert(retracted.subsetOf(onceRetracted))
60
62
61
63
def isEmpty = this eq NotNullInfo .empty
62
64
63
- def retractedInfo = NotNullInfo (Set (), retracted)
65
+ def retractedInfo = NotNullInfo (Set (), retracted, onceRetracted)
66
+
67
+ def onceRetractedInfo = NotNullInfo (Set (), onceRetracted, onceRetracted)
64
68
65
69
/** The sequential combination with another not-null info */
66
70
def seq (that : NotNullInfo ): NotNullInfo =
67
71
if this .isEmpty then that
68
72
else if that.isEmpty then this
69
73
else NotNullInfo (
70
74
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))
72
77
73
78
/** The alternative path combination with another not-null info. Used to merge
74
79
* the nullability info of the two branches of an if.
75
80
*/
76
81
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))
78
90
79
91
object NotNullInfo :
80
- val empty = new NotNullInfo (Set (), Set ())
92
+ val empty = new NotNullInfo (Set (), Set (), Set () )
81
93
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)
84
98
end NotNullInfo
85
99
86
100
/** A pair of not-null sets, depending on whether a condition is `true` or `false` */
0 commit comments