@@ -210,23 +210,22 @@ module Ssa {
210
210
final CfgNode getWriteAccess ( ) { result = write }
211
211
212
212
/**
213
- * Holds if this SSA definition assigns `value` to the underlying variable.
213
+ * Holds if this SSA definition assigns `value` to the underlying
214
+ * variable.
214
215
*
215
- * This is either a direct assignment, `x = value`, or an assignment via
216
- * simple pattern matching
217
- *
218
- * ```rb
219
- * case value
220
- * in Foo => x then ...
221
- * in y => then ...
222
- * end
223
- * ```
216
+ * This is either the value in a direct assignment, `x = value`, or in a
217
+ * `let` statement, `let x = value`. Note that patterns on the rhs. are
218
+ * currently not supported.
224
219
*/
225
220
predicate assigns ( ExprCfgNode value ) {
226
- exists ( AssignmentExprCfgNode ae , BasicBlock bb , int i |
227
- this .definesAt ( _, bb , i ) and
228
- ae .getLhs ( ) = bb .getNode ( i ) and
229
- value = ae .getRhs ( )
221
+ exists ( AssignmentExprCfgNode ae |
222
+ ae .getLhs ( ) = write and
223
+ ae .getRhs ( ) = value
224
+ )
225
+ or
226
+ exists ( LetStmtCfgNode ls |
227
+ ls .getPat ( ) = write and
228
+ ls .getInitializer ( ) = value
230
229
)
231
230
}
232
231
@@ -338,4 +337,37 @@ module Ssa {
338
337
339
338
override Location getLocation ( ) { result = this .getBasicBlock ( ) .getLocation ( ) }
340
339
}
340
+
341
+ /**
342
+ * An SSA definition inserted at a call that may update the value of a captured
343
+ * variable. For example, in
344
+ *
345
+ * ```rb
346
+ * fn capture_mut() {
347
+ * let mut y = 0;
348
+ * (0..5).for_each(|| {
349
+ * y += x
350
+ * });
351
+ * y
352
+ * }
353
+ * ```
354
+ *
355
+ * a definition for `y` is inserted at the call to `for_each`.
356
+ */
357
+ class CapturedCallDefinition extends Definition , SsaImpl:: UncertainWriteDefinition {
358
+ CapturedCallDefinition ( ) {
359
+ exists ( Variable v , BasicBlock bb , int i |
360
+ this .definesAt ( v , bb , i ) and
361
+ SsaImpl:: capturedCallWrite ( _, bb , i , v )
362
+ )
363
+ }
364
+
365
+ /**
366
+ * Gets the immediately preceding definition. Since this update is uncertain,
367
+ * the value from the preceding definition might still be valid.
368
+ */
369
+ final Definition getPriorDefinition ( ) { result = SsaImpl:: uncertainWriteDefinitionInput ( this ) }
370
+
371
+ override string toString ( ) { result = "<captured exit> " + this .getSourceVariable ( ) }
372
+ }
341
373
}
0 commit comments