@@ -4,7 +4,7 @@ package typer
4
4
5
5
import core ._
6
6
import Types ._ , Contexts ._ , Symbols ._ , Decorators ._ , Constants ._
7
- import annotation .{ tailrec , infix }
7
+ import annotation .tailrec
8
8
import StdNames .nme
9
9
import util .Property
10
10
@@ -20,14 +20,20 @@ object Nullables with
20
20
21
21
def isEmpty = this eq NotNullInfo .empty
22
22
23
+ def retractedInfo = NotNullInfo (Set (), retracted)
24
+
23
25
/** The sequential combination with another not-null info */
24
- @ infix def seq (that : NotNullInfo ): NotNullInfo =
26
+ def seq (that : NotNullInfo ): NotNullInfo =
25
27
if this .isEmpty then that
26
28
else if that.isEmpty then this
27
29
else NotNullInfo (
28
30
this .asserted.union(that.asserted).diff(that.retracted),
29
31
this .retracted.union(that.retracted).diff(that.asserted))
30
32
33
+ /** The alternative path combination with another not-null info */
34
+ def alt (that : NotNullInfo ): NotNullInfo =
35
+ NotNullInfo (this .asserted.intersect(that.asserted), this .retracted.union(that.retracted))
36
+
31
37
object NotNullInfo with
32
38
val empty = new NotNullInfo (Set (), Set ())
33
39
def apply (asserted : Set [TermRef ], retracted : Set [TermRef ]): NotNullInfo =
@@ -124,24 +130,28 @@ object Nullables with
124
130
125
131
given (tree : Tree )
126
132
127
- /* The `tree` with added attachment stating that all paths in `refs` are not-null */
133
+ /* The `tree` with added nullability attachment */
128
134
def withNotNullInfo (info : NotNullInfo ): tree.type =
129
135
if ! info.isEmpty then tree.putAttachment(NNInfo , info)
130
136
tree
131
137
132
- def withNotNullRefs (refs : Set [TermRef ]) = tree.withNotNullInfo(NotNullInfo (refs, Set ()))
133
-
134
- /* The paths that are known to be not null after execution of `tree` terminates normally */
138
+ /* The nullability info of `tree` */
135
139
def notNullInfo (given Context ): NotNullInfo =
136
140
stripInlined(tree).getAttachment(NNInfo ) match
137
141
case Some (info) if ! curCtx.erasedTypes => info
138
142
case _ => NotNullInfo .empty
139
143
144
+ /* The nullability info of `tree`, assuming it is a condition that evaluates to `c` */
145
+ def notNullInfoIf (c : Boolean )(given Context ): NotNullInfo =
146
+ val cond = tree.notNullConditional
147
+ if cond.isEmpty then tree.notNullInfo
148
+ else tree.notNullInfo.seq(NotNullInfo (if c then cond.ifTrue else cond.ifFalse, Set ()))
149
+
140
150
/** The paths that are known to be not null if the condition represented
141
151
* by `tree` yields `true` or `false`. Two empty sets if `tree` is not
142
152
* a condition.
143
153
*/
144
- def notNullConditional (given Context ): NotNullConditional =
154
+ private def notNullConditional (given Context ): NotNullConditional =
145
155
stripBlock(tree).getAttachment(NNConditional ) match
146
156
case Some (cond) if ! curCtx.erasedTypes => cond
147
157
case _ => NotNullConditional .empty
@@ -153,21 +163,20 @@ object Nullables with
153
163
154
164
/** The current context augmented with nullability information,
155
165
* assuming the result of the condition represented by `tree` is the same as
156
- * the value of `tru`. The current context if `tree` is not a condition .
166
+ * the value of `c` .
157
167
*/
158
- def nullableContext (tru : Boolean )(given Context ): Context =
159
- val cond = tree.notNullConditional
160
- if cond.isEmpty then curCtx
161
- else curCtx.addNotNullRefs(if tru then cond.ifTrue else cond.ifFalse)
168
+ def nullableContextIf (c : Boolean )(given Context ): Context =
169
+ val info = tree.notNullInfoIf(c)
170
+ if info.isEmpty then curCtx else curCtx.addNotNullInfo(info)
162
171
163
172
/** The context to use for the arguments of the function represented by `tree`.
164
173
* This is the current context, augmented with nullability information
165
174
* of the left argument, if the application is a boolean `&&` or `||`.
166
175
*/
167
176
def nullableInArgContext (given Context ): Context = tree match
168
177
case Select (x, _) if ! curCtx.erasedTypes =>
169
- if tree.symbol == defn.Boolean_&& then x.nullableContext (true )
170
- else if tree.symbol == defn.Boolean_|| then x.nullableContext (false )
178
+ if tree.symbol == defn.Boolean_&& then x.nullableContextIf (true )
179
+ else if tree.symbol == defn.Boolean_|| then x.nullableContextIf (false )
171
180
else curCtx
172
181
case _ => curCtx
173
182
0 commit comments