@@ -64,6 +64,12 @@ impl Borrow {
6464 }
6565}
6666
67+ impl Default for Borrow {
68+ fn default ( ) -> Self {
69+ Borrow :: Mut ( Mut :: Raw )
70+ }
71+ }
72+
6773/// An item in the borrow stack
6874#[ derive( Copy , Clone , Debug , Hash , PartialEq , Eq ) ]
6975pub enum BorStackItem {
@@ -74,26 +80,33 @@ pub enum BorStackItem {
7480 FnBarrier ( usize )
7581}
7682
77- impl Default for Borrow {
78- fn default ( ) -> Self {
79- Borrow :: Mut ( Mut :: Raw )
83+ impl BorStackItem {
84+ #[ inline( always) ]
85+ pub fn is_fn_barrier ( self ) -> bool {
86+ match self {
87+ BorStackItem :: FnBarrier ( _) => true ,
88+ _ => false ,
89+ }
8090 }
8191}
8292
83- /// What kind of reference are we talking about?
93+ /// What kind of usage of the pointer are we talking about?
8494#[ derive( Copy , Clone , Debug , Hash , PartialEq , Eq ) ]
85- pub enum RefKind {
86- Mut ,
87- Shr ,
95+ pub enum UsageKind {
96+ /// Write, or create &mut
97+ Write ,
98+ /// Read, or create &
99+ Read ,
100+ /// Create *
88101 Raw ,
89102}
90103
91- impl From < Option < hir:: Mutability > > for RefKind {
104+ impl From < Option < hir:: Mutability > > for UsageKind {
92105 fn from ( mutbl : Option < hir:: Mutability > ) -> Self {
93106 match mutbl {
94- None => RefKind :: Raw ,
95- Some ( hir:: MutMutable ) => RefKind :: Mut ,
96- Some ( hir:: MutImmutable ) => RefKind :: Shr ,
107+ None => UsageKind :: Raw ,
108+ Some ( hir:: MutMutable ) => UsageKind :: Write ,
109+ Some ( hir:: MutImmutable ) => UsageKind :: Read ,
97110 }
98111 }
99112}
@@ -112,7 +125,7 @@ impl State {
112125
113126/// Extra per-location state
114127#[ derive( Clone , Debug ) ]
115- struct Stack {
128+ pub struct Stack {
116129 borrows : Vec < BorStackItem > , // used as a stack
117130 frozen_since : Option < Timestamp > ,
118131}
@@ -143,17 +156,17 @@ pub struct Stacks {
143156/// Core operations
144157impl < ' tcx > Stack {
145158 /// Check if `bor` could be activated by unfreezing and popping.
146- /// `ref_kind ` indicates whether this is being used to read/write (or, equivalently, to
159+ /// `usage ` indicates whether this is being used to read/write (or, equivalently, to
147160 /// borrow as &/&mut), or to borrow as raw.
148161 /// Returns `Err` if the answer is "no"; otherwise the data says
149162 /// what needs to happen to activate this: `None` = nothing,
150163 /// `Some(n)` = unfreeze and make item `n` the top item of the stack.
151- fn reactivatable ( & self , bor : Borrow , ref_kind : RefKind ) -> Result < Option < usize > , String > {
164+ fn reactivatable ( & self , bor : Borrow , usage : UsageKind ) -> Result < Option < usize > , String > {
152165 let mut_borrow = match bor {
153166 Borrow :: Frz ( since) =>
154167 // The only way to reactivate a `Frz` is if this is already frozen.
155168 return match self . frozen_since {
156- _ if ref_kind == RefKind :: Mut =>
169+ _ if usage == UsageKind :: Write =>
157170 Err ( format ! ( "Using a shared borrow for mutation" ) ) ,
158171 None =>
159172 Err ( format ! ( "Location should be frozen but it is not" ) ) ,
@@ -163,10 +176,11 @@ impl<'tcx> Stack {
163176 Err ( format ! ( "Location should be frozen since {} but it is only frozen \
164177 since {}", since, loc) ) ,
165178 } ,
166- Borrow :: Mut ( Mut :: Raw ) if self . is_frozen ( ) && ref_kind != RefKind :: Mut =>
179+ Borrow :: Mut ( Mut :: Raw ) if self . is_frozen ( ) && usage != UsageKind :: Write =>
167180 // Non-mutating access with a raw from a frozen location is a special case: The
168181 // shared refs do not mind raw reads, and the raw itself does not assume any
169- // exclusivity. So we do not even require there to be a raw on the stack.
182+ // exclusivity. So we do not even require there to be a raw on the stack,
183+ // the raw is instead "matched" by the fact that this location is frozen.
170184 // This does not break the assumption that an `&mut` we own is
171185 // exclusive for reads, because there we have the invariant that
172186 // the location is *not* frozen.
@@ -183,7 +197,7 @@ impl<'tcx> Stack {
183197 if loc == mut_borrow {
184198 // We found it! This is good to know.
185199 // Yet, maybe we do not really want to pop?
186- if ref_kind == RefKind :: Shr && self . is_frozen ( ) {
200+ if usage == UsageKind :: Read && self . is_frozen ( ) {
187201 // Whoever had exclusive access to this location allowed it
188202 // to become frozen. That can only happen if they reborrowed
189203 // to a shared ref, at which point they gave up on exclusive access.
@@ -204,10 +218,10 @@ impl<'tcx> Stack {
204218 Err ( format ! ( "Mutable borrow-to-reactivate ({:?}) does not exist on the stack" , mut_borrow) )
205219 }
206220
207- /// Reactive `bor` for this stack. `ref_kind ` indicates whether this is being
221+ /// Reactive `bor` for this stack. `usage ` indicates whether this is being
208222 /// used to read/write (or, equivalently, to borrow as &/&mut), or to borrow as raw.
209- fn reactivate ( & mut self , bor : Borrow , ref_kind : RefKind ) -> EvalResult < ' tcx > {
210- let action = match self . reactivatable ( bor, ref_kind ) {
223+ fn reactivate ( & mut self , bor : Borrow , usage : UsageKind ) -> EvalResult < ' tcx > {
224+ let action = match self . reactivatable ( bor, usage ) {
211225 Ok ( action) => action,
212226 Err ( err) => return err ! ( MachineError ( err) ) ,
213227 } ;
@@ -274,20 +288,20 @@ impl State {
274288
275289/// Higher-level operations
276290impl < ' tcx > Stacks {
277- /// The single most operation: Make sure that using `ptr` as `ref_kind ` is okay,
291+ /// The single most operation: Make sure that using `ptr` as `usage ` is okay,
278292 /// and if `new_bor` is present then make that the new current borrow.
279293 fn use_and_maybe_re_borrow (
280294 & self ,
281295 ptr : Pointer < Borrow > ,
282296 size : Size ,
283- ref_kind : RefKind ,
297+ usage : UsageKind ,
284298 new_bor : Option < Borrow > ,
285299 ) -> EvalResult < ' tcx > {
286300 trace ! ( "use_and_maybe_re_borrow of tag {:?} as {:?}, new {:?}: {:?}, size {}" ,
287- ptr. tag, ref_kind , new_bor, ptr, size. bytes( ) ) ;
301+ ptr. tag, usage , new_bor, ptr, size. bytes( ) ) ;
288302 let mut stacks = self . stacks . borrow_mut ( ) ;
289303 for stack in stacks. iter_mut ( ptr. offset , size) {
290- stack. reactivate ( ptr. tag , ref_kind ) ?;
304+ stack. reactivate ( ptr. tag , usage ) ?;
291305 if let Some ( new_bor) = new_bor {
292306 stack. initiate ( new_bor) ;
293307 }
@@ -303,7 +317,7 @@ impl<'tcx> Stacks {
303317 size : Size ,
304318 ) -> EvalResult < ' tcx > {
305319 // Reads behave exactly like the first half of a reborrow-to-shr
306- self . use_and_maybe_re_borrow ( ptr, size, RefKind :: Shr , None )
320+ self . use_and_maybe_re_borrow ( ptr, size, UsageKind :: Read , None )
307321 }
308322
309323 #[ inline( always) ]
@@ -313,7 +327,7 @@ impl<'tcx> Stacks {
313327 size : Size ,
314328 ) -> EvalResult < ' tcx > {
315329 // Writes behave exactly like the first half of a reborrow-to-mut
316- self . use_and_maybe_re_borrow ( ptr, size, RefKind :: Mut , None )
330+ self . use_and_maybe_re_borrow ( ptr, size, UsageKind :: Write , None )
317331 }
318332
319333 pub fn memory_deallocated (
@@ -322,7 +336,7 @@ impl<'tcx> Stacks {
322336 size : Size ,
323337 ) -> EvalResult < ' tcx > {
324338 // This is like mutating
325- self . use_and_maybe_re_borrow ( ptr, size, RefKind :: Mut , None )
339+ self . use_and_maybe_re_borrow ( ptr, size, UsageKind :: Write , None )
326340 // FIXME: Error out of there are any barriers?
327341 }
328342
@@ -346,7 +360,7 @@ pub trait EvalContextExt<'tcx> {
346360 ptr : Pointer < Borrow > ,
347361 pointee_ty : Ty < ' tcx > ,
348362 size : Size ,
349- ref_kind : RefKind ,
363+ usage : UsageKind ,
350364 ) -> EvalResult < ' tcx , Borrow > ;
351365
352366
@@ -355,7 +369,7 @@ pub trait EvalContextExt<'tcx> {
355369 ptr : Pointer < Borrow > ,
356370 pointee_ty : Ty < ' tcx > ,
357371 size : Size ,
358- ref_kind : RefKind ,
372+ usage : UsageKind ,
359373 ) -> EvalResult < ' tcx , Borrow > ;
360374
361375 fn tag_new_allocation (
@@ -378,12 +392,12 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
378392 ptr : Pointer < Borrow > ,
379393 pointee_ty : Ty < ' tcx > ,
380394 size : Size ,
381- ref_kind : RefKind ,
395+ usage : UsageKind ,
382396 ) -> EvalResult < ' tcx , Borrow > {
383397 let time = self . machine . stacked_borrows . increment_clock ( ) ;
384- let new_bor = match ref_kind {
385- RefKind :: Mut => Borrow :: Mut ( Mut :: Uniq ( time) ) ,
386- RefKind :: Shr =>
398+ let new_bor = match usage {
399+ UsageKind :: Write => Borrow :: Mut ( Mut :: Uniq ( time) ) ,
400+ UsageKind :: Read =>
387401 // FIXME This does not do enough checking when only part of the data has
388402 // interior mutability. When the type is `(i32, Cell<i32>)`, we want the
389403 // first field to be frozen but not the second.
@@ -393,18 +407,18 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
393407 // Shared reference with interior mutability.
394408 Borrow :: Mut ( Mut :: Raw )
395409 } ,
396- RefKind :: Raw => Borrow :: Mut ( Mut :: Raw ) ,
410+ UsageKind :: Raw => Borrow :: Mut ( Mut :: Raw ) ,
397411 } ;
398412 trace ! ( "tag_reference: Creating new reference ({:?}) for {:?} (pointee {}, size {}): {:?}" ,
399- ref_kind , ptr, pointee_ty, size. bytes( ) , new_bor) ;
413+ usage , ptr, pointee_ty, size. bytes( ) , new_bor) ;
400414
401415 // Make sure this reference is not dangling or so
402416 self . memory ( ) . check_bounds ( ptr, size, false ) ?;
403417
404418 // Update the stacks. We cannot use `get_mut` becuse this might be immutable
405419 // memory.
406420 let alloc = self . memory ( ) . get ( ptr. alloc_id ) . expect ( "We checked that the ptr is fine!" ) ;
407- alloc. extra . use_and_maybe_re_borrow ( ptr, size, ref_kind , Some ( new_bor) ) ?;
421+ alloc. extra . use_and_maybe_re_borrow ( ptr, size, usage , Some ( new_bor) ) ?;
408422
409423 Ok ( new_bor)
410424 }
@@ -418,39 +432,39 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
418432 ptr : Pointer < Borrow > ,
419433 pointee_ty : Ty < ' tcx > ,
420434 size : Size ,
421- ref_kind : RefKind ,
435+ usage : UsageKind ,
422436 ) -> EvalResult < ' tcx , Borrow > {
423437 trace ! ( "tag_reference: Accessing reference ({:?}) for {:?} (pointee {}, size {})" ,
424- ref_kind , ptr, pointee_ty, size. bytes( ) ) ;
438+ usage , ptr, pointee_ty, size. bytes( ) ) ;
425439 // In principle we should not have to do anything here. However, with transmutes involved,
426- // it can happen that the tag of `ptr` does not actually match `ref_kind `, and we
440+ // it can happen that the tag of `ptr` does not actually match `usage `, and we
427441 // should adjust for that.
428442 // Notably, the compiler can introduce such transmutes by optimizing away `&[mut]*`.
429443 // That can transmute a raw ptr to a (shared/mut) ref, and a mut ref to a shared one.
430- match ( ref_kind , ptr. tag ) {
431- ( RefKind :: Raw , _) => {
444+ match ( usage , ptr. tag ) {
445+ ( UsageKind :: Raw , _) => {
432446 // Don't use the tag, this is a raw access! Even if there is a tag,
433447 // that means transmute happened and we ignore the tag.
434448 // Also don't do any further validation, this is raw after all.
435449 return Ok ( Borrow :: Mut ( Mut :: Raw ) ) ;
436450 }
437- ( RefKind :: Mut , Borrow :: Mut ( Mut :: Uniq ( _) ) ) |
438- ( RefKind :: Shr , Borrow :: Frz ( _) ) |
439- ( RefKind :: Shr , Borrow :: Mut ( Mut :: Raw ) ) => {
451+ ( UsageKind :: Write , Borrow :: Mut ( Mut :: Uniq ( _) ) ) |
452+ ( UsageKind :: Read , Borrow :: Frz ( _) ) |
453+ ( UsageKind :: Read , Borrow :: Mut ( Mut :: Raw ) ) => {
440454 // Expected combinations. Nothing to do.
441455 // FIXME: We probably shouldn't accept this if we got a raw shr without
442456 // interior mutability.
443457 }
444- ( RefKind :: Mut , Borrow :: Mut ( Mut :: Raw ) ) => {
458+ ( UsageKind :: Write , Borrow :: Mut ( Mut :: Raw ) ) => {
445459 // Raw transmuted to mut ref. Keep this as raw access.
446460 // We cannot reborrow here; there might be a raw in `&(*var).1` where
447461 // `var` is an `&mut`. The other field of the struct might be already frozen,
448462 // also using `var`, and that would be okay.
449463 }
450- ( RefKind :: Shr , Borrow :: Mut ( Mut :: Uniq ( _) ) ) => {
464+ ( UsageKind :: Read , Borrow :: Mut ( Mut :: Uniq ( _) ) ) => {
451465 // A mut got transmuted to shr. The mut borrow must be reactivatable.
452466 }
453- ( RefKind :: Mut , Borrow :: Frz ( _) ) => {
467+ ( UsageKind :: Write , Borrow :: Frz ( _) ) => {
454468 // This is just invalid.
455469 // If we ever allow this, we have to consider what we do when a turn a
456470 // `Raw`-tagged `&mut` into a raw pointer pointing to a frozen location.
@@ -467,8 +481,12 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
467481 // We need `iter_mut` because `iter` would skip gaps!
468482 for stack in stacks. iter_mut ( ptr. offset , size) {
469483 // Conservatively assume that we will only read.
470- if let Err ( err) = stack. reactivatable ( ptr. tag , RefKind :: Shr ) {
471- return err ! ( MachineError ( format!( "Encountered {:?} reference with non-reactivatable tag: {}" , ref_kind, err) ) )
484+ if let Err ( err) = stack. reactivatable ( ptr. tag , UsageKind :: Read ) {
485+ return err ! ( MachineError ( format!(
486+ "Encountered {} reference with non-reactivatable tag: {}" ,
487+ if usage == UsageKind :: Write { "mutable" } else { "shared" } ,
488+ err
489+ ) ) )
472490 }
473491 }
474492 // All is good.
0 commit comments