@@ -137,75 +137,64 @@ impl<'tcx> Stack {
137
137
}
138
138
139
139
/// Check if `bor` could be activated by unfreezing and popping.
140
- /// This should be in sync with `reactivate`!
141
- fn reactivatable ( & self , bor : Borrow ) -> bool {
142
- if self . check ( bor) {
143
- return true ;
144
- }
145
-
146
- let acc_m = match bor {
147
- Borrow :: Frz ( _) => return false ,
148
- Borrow :: Mut ( acc_m) => acc_m
149
- } ;
150
- // This is where we would unfreeze.
151
- for & itm in self . borrows . iter ( ) . rev ( ) {
152
- match itm {
153
- BorStackItem :: FnBarrier ( _) => return false ,
154
- BorStackItem :: Mut ( loc_m) => {
155
- if loc_m == acc_m { return true ; }
156
- // Go on looking.
157
- }
158
- }
159
- }
160
- // Nothing to be found.
161
- false
162
- }
163
-
164
- /// Reactive `bor` for this stack. If `force_mut` is set, we want to aggressively
165
- /// unfreeze this location (because we are about to mutate, so a frozen `Raw` is not okay).
166
- fn reactivate ( & mut self , bor : Borrow , force_mut : bool ) -> EvalResult < ' tcx > {
140
+ /// `force_mut` indicates whether being frozen is potentially acceptable.
141
+ /// Returns `Err` if the answer is "no"; otherwise the data says
142
+ /// what needs to happen to activate this: `None` = nothing,
143
+ /// `Some(n)` = unfreeze and make item `n` the top item of the stack.
144
+ fn reactivatable ( & self , bor : Borrow , force_mut : bool ) -> Result < Option < usize > , String > {
167
145
// Unless mutation is bound to happen, do NOT change anything if `bor` is already active.
168
146
// In particular, if it is a `Mut(Raw)` and we are frozen, this should be a NOP.
169
147
if !force_mut && self . check ( bor) {
170
- return Ok ( ( ) ) ;
148
+ return Ok ( None ) ;
171
149
}
172
150
173
151
let acc_m = match bor {
174
152
Borrow :: Frz ( since) =>
175
- if force_mut {
176
- return err ! ( MachineError ( format!( "Using a shared borrow for mutation" ) ) )
153
+ return Err ( if force_mut {
154
+ format ! ( "Using a shared borrow for mutation" )
177
155
} else {
178
- return err ! ( MachineError ( format!(
156
+ format ! (
179
157
"Location should be frozen since {} but {}" ,
180
158
since,
181
159
match self . frozen_since {
182
160
None => format!( "it is not frozen at all" ) ,
183
161
Some ( since) => format!( "it is only frozen since {}" , since) ,
184
162
}
185
- ) ) )
186
- }
187
- Borrow :: Mut ( acc_m) => acc_m,
163
+ )
164
+ } ) ,
165
+ Borrow :: Mut ( acc_m) => acc_m
188
166
} ;
189
- // We definitely have to unfreeze this, even if we use the topmost item.
190
- if self . frozen_since . is_some ( ) {
191
- trace ! ( "reactivate: Unfreezing" ) ;
192
- }
193
- self . frozen_since = None ;
194
- // Pop until we see the one we are looking for.
195
- while let Some ( & itm) = self . borrows . last ( ) {
167
+ // This is where we would unfreeze.
168
+ for ( idx, & itm) in self . borrows . iter ( ) . enumerate ( ) . rev ( ) {
196
169
match itm {
197
- BorStackItem :: FnBarrier ( _) => {
198
- return err ! ( MachineError ( format!( "Trying to reactivate a borrow that lives behind a barrier" ) ) ) ;
199
- }
170
+ BorStackItem :: FnBarrier ( _) =>
171
+ return Err ( format ! ( "Trying to reactivate a mutable borrow ({:?}) that lives behind a barrier" , acc_m) ) ,
200
172
BorStackItem :: Mut ( loc_m) => {
201
- if loc_m == acc_m { return Ok ( ( ) ) ; }
202
- trace ! ( "reactivate: Popping {:?}" , itm) ;
203
- self . borrows . pop ( ) ;
173
+ if loc_m == acc_m { return Ok ( Some ( idx) ) ; }
204
174
}
205
175
}
206
176
}
207
177
// Nothing to be found.
208
- err ! ( MachineError ( format!( "Borrow-to-reactivate does not exist on the stack" ) ) )
178
+ Err ( format ! ( "Mutable borrow-to-reactivate ({:?}) does not exist on the stack" , acc_m) )
179
+ }
180
+
181
+ /// Reactive `bor` for this stack. If `force_mut` is set, we want to aggressively
182
+ /// unfreeze this location (because we are about to mutate, so a frozen `Raw` is not okay).
183
+ fn reactivate ( & mut self , bor : Borrow , force_mut : bool ) -> EvalResult < ' tcx > {
184
+ let action = match self . reactivatable ( bor, force_mut) {
185
+ Ok ( action) => action,
186
+ Err ( err) => return err ! ( MachineError ( err) ) ,
187
+ } ;
188
+
189
+ match action {
190
+ None => { } , // nothing to do
191
+ Some ( top) => {
192
+ self . frozen_since = None ;
193
+ self . borrows . truncate ( top+1 ) ;
194
+ }
195
+ }
196
+
197
+ Ok ( ( ) )
209
198
}
210
199
211
200
/// Initiate `bor`; mostly this means freezing or pushing.
@@ -471,8 +460,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
471
460
// be shared reborrows that we are about to invalidate with this access.
472
461
// We cannot invalidate them aggressively here because the deref might also be
473
462
// to just create more shared refs.
474
- if ! stack. reactivatable ( ptr. tag ) {
475
- return err ! ( MachineError ( format!( "Encountered {:?} reference with non-reactivatable tag {:? }" , ref_kind, ptr . tag ) ) )
463
+ if let Err ( err ) = stack. reactivatable ( ptr. tag , /*force_mut*/ false ) {
464
+ return err ! ( MachineError ( format!( "Encountered {:?} reference with non-reactivatable tag: { }" , ref_kind, err ) ) )
476
465
}
477
466
}
478
467
// All is good.
0 commit comments