@@ -164,6 +164,39 @@ class Guard extends ExprParent {
164
164
)
165
165
}
166
166
167
+ /**
168
+ * Holds if this guard tests whether `testedExpr` has type `testedType`.
169
+ *
170
+ * `restricted` is true if the test applies additional restrictions on top of just `testedType`, and so
171
+ * this guard failing does not guarantee `testedExpr` is *not* a `testedType`-- for example,
172
+ * matching `record R(Object o)` with `case R(String s)` is a guard with an additional restriction on the
173
+ * type of field `o`, so the guard passing guarantees `testedExpr` is an `R`, but it failing does not
174
+ * guarantee `testedExpr` is not an `R`.
175
+ */
176
+ predicate appliesTypeTest ( Expr testedExpr , Type testedType , boolean restricted ) {
177
+ (
178
+ exists ( InstanceOfExpr ioe | this = ioe |
179
+ testedExpr = ioe .getExpr ( ) and
180
+ testedType = ioe .getSyntacticCheckedType ( )
181
+ )
182
+ or
183
+ exists ( PatternCase pc | this = pc |
184
+ pc .getSelectorExpr ( ) = testedExpr and
185
+ testedType = pc .getPattern ( ) .getType ( )
186
+ )
187
+ ) and
188
+ (
189
+ if
190
+ exists ( RecordPatternExpr rpe |
191
+ rpe = [ this .( InstanceOfExpr ) .getPattern ( ) , this .( PatternCase ) .getPattern ( ) ]
192
+ |
193
+ not rpe .isUnrestricted ( )
194
+ )
195
+ then restricted = true
196
+ else restricted = false
197
+ )
198
+ }
199
+
167
200
/**
168
201
* Holds if the evaluation of this guard to `branch` corresponds to the edge
169
202
* from `bb1` to `bb2`.
@@ -223,60 +256,6 @@ class Guard extends ExprParent {
223
256
}
224
257
}
225
258
226
- /**
227
- * A `Guard` that tests an expression's type -- that is, an `instanceof T` or a
228
- * `case T varname` pattern case.
229
- */
230
- class TypeTestGuard extends Guard {
231
- Expr testedExpr ;
232
- Type testedType ;
233
-
234
- TypeTestGuard ( ) {
235
- exists ( InstanceOfExpr ioe | this = ioe |
236
- testedExpr = ioe .getExpr ( ) and
237
- testedType = ioe .getSyntacticCheckedType ( )
238
- )
239
- or
240
- exists ( PatternCase pc | this = pc |
241
- pc .getSelectorExpr ( ) = testedExpr and
242
- testedType = pc .getPattern ( ) .getType ( )
243
- )
244
- }
245
-
246
- /**
247
- * Gets the record pattern this type test binds to, if any.
248
- */
249
- PatternExpr getPattern ( ) {
250
- result = this .( InstanceOfExpr ) .getPattern ( )
251
- or
252
- result = this .( PatternCase ) .getPattern ( )
253
- }
254
-
255
- /**
256
- * Holds if this guard tests whether `e` has type `t` on `testedBranch`.
257
- *
258
- * Note that record patterns that make at least one tighter restriction than the record's definition
259
- * (e.g. matching `record R(Object)` with `case R(String)`) means this only guarantees the tested type
260
- * on the true branch (i.e., entering such a case guarantees `testedExpr` is a `testedType`, but failing
261
- * the type test could mean a nested record or binding pattern didn't match but `testedExpr` is still
262
- * of type `testedType`.)
263
- */
264
- predicate appliesTypeTest ( Expr e , Type t , boolean testedBranch ) {
265
- e = testedExpr and
266
- t = testedType and
267
- (
268
- testedBranch = true
269
- or
270
- testedBranch = false and
271
- (
272
- this .getPattern ( ) .asRecordPattern ( ) .isUnrestricted ( )
273
- or
274
- not this .getPattern ( ) instanceof RecordPatternExpr
275
- )
276
- )
277
- }
278
- }
279
-
280
259
private predicate switchCaseControls ( SwitchCase sc , BasicBlock bb ) {
281
260
exists ( BasicBlock caseblock |
282
261
caseblock .getFirstNode ( ) = sc .getControlFlowNode ( ) and
0 commit comments