2
2
3
3
use std:: borrow:: Borrow ;
4
4
5
- use rustc:: mir:: { self , BasicBlock , Location } ;
5
+ use rustc:: mir:: { self , BasicBlock , Location , TerminatorKind } ;
6
6
use rustc_index:: bit_set:: BitSet ;
7
7
8
8
use super :: { Analysis , Results } ;
@@ -29,14 +29,14 @@ where
29
29
30
30
pos : CursorPosition ,
31
31
32
- /// When this flag is set, the cursor is pointing at a `Call` terminator whose call return
33
- /// effect has been applied to `state`.
32
+ /// When this flag is set, the cursor is pointing at a `Call` or `Yield` terminator whose call
33
+ /// return or resume effect has been applied to `state`.
34
34
///
35
- /// This flag helps to ensure that multiple calls to `seek_after_assume_call_returns ` with the
35
+ /// This flag helps to ensure that multiple calls to `seek_after_assume_success ` with the
36
36
/// same target will result in exactly one invocation of `apply_call_return_effect`. It is
37
37
/// sufficient to clear this only in `seek_to_block_start`, since seeking away from a
38
38
/// terminator will always require a cursor reset.
39
- call_return_effect_applied : bool ,
39
+ success_effect_applied : bool ,
40
40
}
41
41
42
42
impl < ' mir , ' tcx , A , R > ResultsCursor < ' mir , ' tcx , A , R >
50
50
body,
51
51
pos : CursorPosition :: BlockStart ( mir:: START_BLOCK ) ,
52
52
state : results. borrow ( ) . entry_sets [ mir:: START_BLOCK ] . clone ( ) ,
53
- call_return_effect_applied : false ,
53
+ success_effect_applied : false ,
54
54
results,
55
55
}
56
56
}
@@ -76,14 +76,14 @@ where
76
76
pub fn seek_to_block_start ( & mut self , block : BasicBlock ) {
77
77
self . state . overwrite ( & self . results . borrow ( ) . entry_sets [ block] ) ;
78
78
self . pos = CursorPosition :: BlockStart ( block) ;
79
- self . call_return_effect_applied = false ;
79
+ self . success_effect_applied = false ;
80
80
}
81
81
82
82
/// Advances the cursor to hold all effects up to and including to the "before" effect of the
83
83
/// statement (or terminator) at the given location.
84
84
///
85
85
/// If you wish to observe the full effect of a statement or terminator, not just the "before"
86
- /// effect, use `seek_after` or `seek_after_assume_call_returns `.
86
+ /// effect, use `seek_after` or `seek_after_assume_success `.
87
87
pub fn seek_before ( & mut self , target : Location ) {
88
88
assert ! ( target <= self . body. terminator_loc( target. block) ) ;
89
89
self . seek_ ( target, false ) ;
@@ -93,15 +93,15 @@ where
93
93
/// terminators) up to and including the `target`.
94
94
///
95
95
/// If the `target` is a `Call` terminator, any call return effect for that terminator will
96
- /// **not** be observed. Use `seek_after_assume_call_returns ` if you wish to observe the call
96
+ /// **not** be observed. Use `seek_after_assume_success ` if you wish to observe the call
97
97
/// return effect.
98
98
pub fn seek_after ( & mut self , target : Location ) {
99
99
assert ! ( target <= self . body. terminator_loc( target. block) ) ;
100
100
101
101
// If we have already applied the call return effect, we are currently pointing at a `Call`
102
102
// terminator. Unconditionally reset the dataflow cursor, since there is no way to "undo"
103
103
// the call return effect.
104
- if self . call_return_effect_applied {
104
+ if self . success_effect_applied {
105
105
self . seek_to_block_start ( target. block ) ;
106
106
}
107
107
@@ -111,25 +111,25 @@ where
111
111
/// Advances the cursor to hold all effects up to and including of the statement (or
112
112
/// terminator) at the given location.
113
113
///
114
- /// If the `target` is a `Call` terminator, any call return effect for that terminator will
115
- /// be observed. Use `seek_after` if you do **not** wish to observe the call return effect.
116
- pub fn seek_after_assume_call_returns ( & mut self , target : Location ) {
114
+ /// If the `target` is a `Call` or `Yield` terminator, any call return or resume effect for that
115
+ /// terminator will be observed. Use `seek_after` if you do **not** wish to observe the
116
+ /// "success" effect.
117
+ pub fn seek_after_assume_success ( & mut self , target : Location ) {
117
118
let terminator_loc = self . body . terminator_loc ( target. block ) ;
118
119
assert ! ( target. statement_index <= terminator_loc. statement_index) ;
119
120
120
121
self . seek_ ( target, true ) ;
121
122
122
- if target != terminator_loc {
123
+ if target != terminator_loc || self . success_effect_applied {
123
124
return ;
124
125
}
125
126
127
+ // Apply the effect of the "success" path of the terminator.
128
+
129
+ self . success_effect_applied = true ;
126
130
let terminator = self . body . basic_blocks ( ) [ target. block ] . terminator ( ) ;
127
- if let mir:: TerminatorKind :: Call {
128
- destination : Some ( ( return_place, _) ) , func, args, ..
129
- } = & terminator. kind
130
- {
131
- if !self . call_return_effect_applied {
132
- self . call_return_effect_applied = true ;
131
+ match & terminator. kind {
132
+ TerminatorKind :: Call { destination : Some ( ( return_place, _) ) , func, args, .. } => {
133
133
self . results . borrow ( ) . analysis . apply_call_return_effect (
134
134
& mut self . state ,
135
135
target. block ,
@@ -138,6 +138,14 @@ where
138
138
return_place,
139
139
) ;
140
140
}
141
+ TerminatorKind :: Yield { resume, resume_arg, .. } => {
142
+ self . results . borrow ( ) . analysis . apply_yield_resume_effect (
143
+ & mut self . state ,
144
+ * resume,
145
+ resume_arg,
146
+ ) ;
147
+ }
148
+ _ => { }
141
149
}
142
150
}
143
151
@@ -172,7 +180,7 @@ where
172
180
self . seek_to_block_start ( target. block )
173
181
}
174
182
175
- // N.B., `call_return_effect_applied ` is checked in `seek_after`, not here.
183
+ // N.B., `success_effect_applied ` is checked in `seek_after`, not here.
176
184
_ => ( ) ,
177
185
}
178
186
0 commit comments