@@ -22,12 +22,16 @@ pub const MAX_PERMITTED_DATA_INCREASE: usize = 1_024 * 10;
2222pub enum BorrowState {
2323 /// Mask to check whether an account is already borrowed.
2424 ///
25- /// This will test both data and lamports borrow state.
25+ /// This will test both data and lamports borrow state. Any position
26+ /// in the borrow byte that is not set means that the account
27+ /// is borrowed in that state.
2628 Borrowed = 0b_1111_1111 ,
2729
2830 /// Mask to check whether an account is already mutably borrowed.
2931 ///
30- /// This will test both data and lamports mutable borrow state.
32+ /// This will test both data and lamports mutable borrow state. If
33+ /// one of the mutably borrowed bits is not set, then the account
34+ /// is mutably borrowed in that state.
3135 MutablyBorrowed = 0b_1000_1000 ,
3236}
3337
@@ -261,18 +265,19 @@ impl AccountInfo {
261265 self . can_borrow_lamports ( ) ?;
262266
263267 let borrow_state = self . raw as * mut u8 ;
268+ // Use one immutable borrow for lamports by subtracting `1` from the
269+ // lamports borrow counter bits; we are guaranteed that there is at
270+ // least one immutable borrow available.
271+ //
264272 // SAFETY: The `borrow_state` is a mutable pointer to the borrow state
265273 // of the account, which is guaranteed to be valid.
266- //
267- // "consumes" one immutable borrow for lamports; we are guaranteed
268- // that there is at least one immutable borrow available.
269- unsafe { * borrow_state -= 1 << LAMPORTS_SHIFT } ;
274+ unsafe { * borrow_state -= 1 << LAMPORTS_BORROW_SHIFT } ;
270275
271276 // return the reference to lamports
272277 Ok ( Ref {
273278 value : unsafe { NonNull :: from ( & ( * self . raw ) . lamports ) } ,
274279 state : unsafe { NonNull :: new_unchecked ( borrow_state) } ,
275- borrow_shift : LAMPORTS_SHIFT ,
280+ borrow_shift : LAMPORTS_BORROW_SHIFT ,
276281 marker : PhantomData ,
277282 } )
278283 }
@@ -284,18 +289,18 @@ impl AccountInfo {
284289 self . can_borrow_mut_lamports ( ) ?;
285290
286291 let borrow_state = self . raw as * mut u8 ;
292+ // Set the mutable lamports borrow bit to `0`; we are guaranteed
293+ // that lamports are not already borrowed in any form.
294+ //
287295 // SAFETY: The `borrow_state` is a mutable pointer to the borrow state
288296 // of the account, which is guaranteed to be valid.
289- //
290- // "consumes" the mutable borrow for lamports; we are guaranteed
291- // that lamports are not already borrowed in any form
292297 unsafe { * borrow_state &= 0b_0111_1111 } ;
293298
294299 // return the mutable reference to lamports
295300 Ok ( RefMut {
296301 value : unsafe { NonNull :: from ( & mut ( * self . raw ) . lamports ) } ,
297302 state : unsafe { NonNull :: new_unchecked ( borrow_state) } ,
298- borrow_mask : LAMPORTS_MASK ,
303+ borrow_bitmask : LAMPORTS_MUTABLE_BORROW_BITMASK ,
299304 marker : PhantomData ,
300305 } )
301306 }
@@ -314,12 +319,14 @@ impl AccountInfo {
314319 pub fn can_borrow_lamports ( & self ) -> Result < ( ) , ProgramError > {
315320 let borrow_state = unsafe { ( * self . raw ) . borrow_state } ;
316321
317- // check if mutable borrow is already taken
318- if borrow_state & 0b_1000_0000 != 0b_1000_0000 {
322+ // Check whether the mutable lamports borrow bit is already in
323+ // use (value `0`) or not. If it is `0`, then the borrow will fail.
324+ if borrow_state & LAMPORTS_MUTABLE_BORROW_BITMASK == 0 {
319325 return Err ( ProgramError :: AccountBorrowFailed ) ;
320326 }
321327
322- // check if we have reached the max immutable borrow count
328+ // Check whether we have reached the maximum immutable lamports borrow count
329+ // or not, i.e., it fails when all immutable lamports borrow bits are `0`.
323330 if borrow_state & 0b_0111_0000 == 0 {
324331 return Err ( ProgramError :: AccountBorrowFailed ) ;
325332 }
@@ -341,7 +348,8 @@ impl AccountInfo {
341348 pub fn can_borrow_mut_lamports ( & self ) -> Result < ( ) , ProgramError > {
342349 let borrow_state = unsafe { ( * self . raw ) . borrow_state } ;
343350
344- // check if any borrow (mutable or immutable) is already taken for lamports
351+ // Check whether any (mutable or immutable) lamports borrow bits are
352+ // in use (value `0`) or not.
345353 if borrow_state & 0b_1111_0000 != 0b_1111_0000 {
346354 return Err ( ProgramError :: AccountBorrowFailed ) ;
347355 }
@@ -356,18 +364,19 @@ impl AccountInfo {
356364 self . can_borrow_data ( ) ?;
357365
358366 let borrow_state = self . raw as * mut u8 ;
367+ // Use one immutable borrow for data by subtracting `1` from the data
368+ // borrow counter bits; we are guaranteed that there is at least one
369+ // immutable borrow available.
370+ //
359371 // SAFETY: The `borrow_state` is a mutable pointer to the borrow state
360372 // of the account, which is guaranteed to be valid.
361- //
362- // "consumes" one immutable borrow for data; we are guaranteed
363- // that there is at least one immutable borrow available
364373 unsafe { * borrow_state -= 1 } ;
365374
366375 // return the reference to data
367376 Ok ( Ref {
368377 value : unsafe { NonNull :: from ( from_raw_parts ( self . data_ptr ( ) , self . data_len ( ) ) ) } ,
369378 state : unsafe { NonNull :: new_unchecked ( borrow_state) } ,
370- borrow_shift : DATA_SHIFT ,
379+ borrow_shift : DATA_BORROW_SHIFT ,
371380 marker : PhantomData ,
372381 } )
373382 }
@@ -379,18 +388,18 @@ impl AccountInfo {
379388 self . can_borrow_mut_data ( ) ?;
380389
381390 let borrow_state = self . raw as * mut u8 ;
391+ // Set the mutable data borrow bit to `0`; we are guaranteed that account
392+ // data is not already borrowed in any form.
393+ //
382394 // SAFETY: The `borrow_state` is a mutable pointer to the borrow state
383395 // of the account, which is guaranteed to be valid.
384- //
385- // "consumes" the mutable borrow for account data; we are guaranteed
386- // that account data are not already borrowed in any form
387396 unsafe { * borrow_state &= 0b_1111_0111 } ;
388397
389398 // return the mutable reference to data
390399 Ok ( RefMut {
391400 value : unsafe { NonNull :: from ( from_raw_parts_mut ( self . data_ptr ( ) , self . data_len ( ) ) ) } ,
392401 state : unsafe { NonNull :: new_unchecked ( borrow_state) } ,
393- borrow_mask : DATA_MASK ,
402+ borrow_bitmask : DATA_MUTABLE_BORROW_BITMASK ,
394403 marker : PhantomData ,
395404 } )
396405 }
@@ -409,13 +418,14 @@ impl AccountInfo {
409418 pub fn can_borrow_data ( & self ) -> Result < ( ) , ProgramError > {
410419 let borrow_state = unsafe { ( * self . raw ) . borrow_state } ;
411420
412- // check if mutable data borrow is already taken (most significant bit
413- // of the data borrow state)
414- if borrow_state & 0b_0000_1000 == 0 {
421+ // Check whether the mutable data borrow bit is already in
422+ // use (value `0`) or not. If it is `0`, then the borrow will fail.
423+ if borrow_state & DATA_MUTABLE_BORROW_BITMASK == 0 {
415424 return Err ( ProgramError :: AccountBorrowFailed ) ;
416425 }
417426
418- // check if we have reached the max immutable data borrow count (7)
427+ // Check whether we have reached the maximum immutable data borrow count
428+ // or not, i.e., it fails when all immutable data borrow bits are `0`.
419429 if borrow_state & 0b_0000_0111 == 0 {
420430 return Err ( ProgramError :: AccountBorrowFailed ) ;
421431 }
@@ -437,7 +447,8 @@ impl AccountInfo {
437447 pub fn can_borrow_mut_data ( & self ) -> Result < ( ) , ProgramError > {
438448 let borrow_state = unsafe { ( * self . raw ) . borrow_state } ;
439449
440- // check if any borrow (mutable or immutable) is already taken for data
450+ // Check whether any (mutable or immutable) data borrow bits are
451+ // in use (value `0`) or not.
441452 if borrow_state & 0b_0000_1111 != 0b_0000_1111 {
442453 return Err ( ProgramError :: AccountBorrowFailed ) ;
443454 }
@@ -610,11 +621,17 @@ impl AccountInfo {
610621 }
611622}
612623
613- /// Bytes to shift to get to the borrow state of lamports.
614- const LAMPORTS_SHIFT : u8 = 4 ;
624+ /// Number of bits of the [`Account::borrow_state`] flag to shift to get to
625+ /// the borrow state bits for lamports.
626+ /// - `7 6 5 4 3 2 1 0`
627+ /// - `x x x x . . . .`
628+ const LAMPORTS_BORROW_SHIFT : u8 = 4 ;
615629
616- /// Bytes to shift to get to the borrow state of data.
617- const DATA_SHIFT : u8 = 0 ;
630+ /// Number of bits of the [`Account::borrow_state`] flag to shift to get to
631+ /// the borrow state bits for account data.
632+ /// - `7 6 5 4 3 2 1 0`
633+ /// - `. . . . x x x x`
634+ const DATA_BORROW_SHIFT : u8 = 0 ;
618635
619636/// Reference to account data or lamports with checked borrow rules.
620637pub struct Ref < ' a , T : ?Sized > {
@@ -682,18 +699,18 @@ impl<T: ?Sized> Drop for Ref<'_, T> {
682699}
683700
684701/// Mask representing the mutable borrow flag for lamports.
685- const LAMPORTS_MASK : u8 = 0b_1000_0000 ;
702+ const LAMPORTS_MUTABLE_BORROW_BITMASK : u8 = 0b_1000_0000 ;
686703
687704/// Mask representing the mutable borrow flag for data.
688- const DATA_MASK : u8 = 0b_0000_1000 ;
705+ const DATA_MUTABLE_BORROW_BITMASK : u8 = 0b_0000_1000 ;
689706
690707/// Mutable reference to account data or lamports with checked borrow rules.
691708pub struct RefMut < ' a , T : ?Sized > {
692709 value : NonNull < T > ,
693710 state : NonNull < u8 > ,
694- /// Indicates the type of borrow (lamports or data) by representing the
695- /// mutable borrow mask .
696- borrow_mask : u8 ,
711+ /// Indicates borrowed field (lamports or data) by storing the bitmask
712+ /// representing the mutable borrow.
713+ borrow_bitmask : u8 ,
697714 /// The `value` raw pointer is only valid while the `&'a T` lives so we claim
698715 /// to hold a reference to it.
699716 marker : PhantomData < & ' a mut T > ,
@@ -712,7 +729,7 @@ impl<'a, T: ?Sized> RefMut<'a, T> {
712729 RefMut {
713730 value : NonNull :: from ( f ( & mut * orig) ) ,
714731 state : orig. state ,
715- borrow_mask : orig. borrow_mask ,
732+ borrow_bitmask : orig. borrow_bitmask ,
716733 marker : PhantomData ,
717734 }
718735 }
@@ -732,7 +749,7 @@ impl<'a, T: ?Sized> RefMut<'a, T> {
732749 Ok ( RefMut {
733750 value,
734751 state : orig. state ,
735- borrow_mask : orig. borrow_mask ,
752+ borrow_bitmask : orig. borrow_bitmask ,
736753 marker : PhantomData ,
737754 } )
738755 }
@@ -756,7 +773,7 @@ impl<T: ?Sized> core::ops::DerefMut for RefMut<'_, T> {
756773impl < T : ?Sized > Drop for RefMut < ' _ , T > {
757774 fn drop ( & mut self ) {
758775 // unset the mutable borrow flag
759- unsafe { * self . state . as_mut ( ) |= self . borrow_mask } ;
776+ unsafe { * self . state . as_mut ( ) |= self . borrow_bitmask } ;
760777 }
761778}
762779
@@ -771,31 +788,31 @@ mod tests {
771788 #[ test]
772789 fn test_data_ref ( ) {
773790 let data: [ u8 ; 4 ] = [ 0 , 1 , 2 , 3 ] ;
774- let mut state = NOT_BORROWED - ( 1 << DATA_SHIFT ) ;
791+ let mut state = NOT_BORROWED - ( 1 << DATA_BORROW_SHIFT ) ;
775792
776793 let ref_data = Ref {
777794 value : NonNull :: from ( & data) ,
778- borrow_shift : DATA_SHIFT ,
795+ borrow_shift : DATA_BORROW_SHIFT ,
779796 // borrow state must be a mutable reference
780797 state : NonNull :: from ( & mut state) ,
781798 marker : PhantomData ,
782799 } ;
783800
784801 let new_ref = Ref :: map ( ref_data, |data| & data[ 1 ] ) ;
785802
786- assert_eq ! ( state, NOT_BORROWED - ( 1 << DATA_SHIFT ) ) ;
803+ assert_eq ! ( state, NOT_BORROWED - ( 1 << DATA_BORROW_SHIFT ) ) ;
787804 assert_eq ! ( * new_ref, 1 ) ;
788805
789806 let Ok ( new_ref) = Ref :: filter_map ( new_ref, |_| Some ( & 3 ) ) else {
790807 unreachable ! ( )
791808 } ;
792809
793- assert_eq ! ( state, NOT_BORROWED - ( 1 << DATA_SHIFT ) ) ;
810+ assert_eq ! ( state, NOT_BORROWED - ( 1 << DATA_BORROW_SHIFT ) ) ;
794811 assert_eq ! ( * new_ref, 3 ) ;
795812
796813 let new_ref = Ref :: filter_map ( new_ref, |_| Option :: < & u8 > :: None ) ;
797814
798- assert_eq ! ( state, NOT_BORROWED - ( 1 << DATA_SHIFT ) ) ;
815+ assert_eq ! ( state, NOT_BORROWED - ( 1 << DATA_BORROW_SHIFT ) ) ;
799816 assert ! ( new_ref. is_err( ) ) ;
800817
801818 drop ( new_ref) ;
@@ -806,31 +823,31 @@ mod tests {
806823 #[ test]
807824 fn test_lamports_ref ( ) {
808825 let lamports: u64 = 10000 ;
809- let mut state = NOT_BORROWED - ( 1 << LAMPORTS_SHIFT ) ;
826+ let mut state = NOT_BORROWED - ( 1 << LAMPORTS_BORROW_SHIFT ) ;
810827
811828 let ref_lamports = Ref {
812829 value : NonNull :: from ( & lamports) ,
813- borrow_shift : LAMPORTS_SHIFT ,
830+ borrow_shift : LAMPORTS_BORROW_SHIFT ,
814831 // borrow state must be a mutable reference
815832 state : NonNull :: from ( & mut state) ,
816833 marker : PhantomData ,
817834 } ;
818835
819836 let new_ref = Ref :: map ( ref_lamports, |_| & 1000 ) ;
820837
821- assert_eq ! ( state, NOT_BORROWED - ( 1 << LAMPORTS_SHIFT ) ) ;
838+ assert_eq ! ( state, NOT_BORROWED - ( 1 << LAMPORTS_BORROW_SHIFT ) ) ;
822839 assert_eq ! ( * new_ref, 1000 ) ;
823840
824841 let Ok ( new_ref) = Ref :: filter_map ( new_ref, |_| Some ( & 2000 ) ) else {
825842 unreachable ! ( )
826843 } ;
827844
828- assert_eq ! ( state, NOT_BORROWED - ( 1 << LAMPORTS_SHIFT ) ) ;
845+ assert_eq ! ( state, NOT_BORROWED - ( 1 << LAMPORTS_BORROW_SHIFT ) ) ;
829846 assert_eq ! ( * new_ref, 2000 ) ;
830847
831848 let new_ref = Ref :: filter_map ( new_ref, |_| Option :: < & i32 > :: None ) ;
832849
833- assert_eq ! ( state, NOT_BORROWED - ( 1 << LAMPORTS_SHIFT ) ) ;
850+ assert_eq ! ( state, NOT_BORROWED - ( 1 << LAMPORTS_BORROW_SHIFT ) ) ;
834851 assert ! ( new_ref. is_err( ) ) ;
835852
836853 drop ( new_ref) ;
@@ -845,7 +862,7 @@ mod tests {
845862
846863 let ref_data = RefMut {
847864 value : NonNull :: from ( & mut data) ,
848- borrow_mask : DATA_MASK ,
865+ borrow_bitmask : DATA_MUTABLE_BORROW_BITMASK ,
849866 // borrow state must be a mutable reference
850867 state : NonNull :: from ( & mut state) ,
851868 marker : PhantomData ,
@@ -873,7 +890,7 @@ mod tests {
873890
874891 let ref_lamports = RefMut {
875892 value : NonNull :: from ( & mut lamports) ,
876- borrow_mask : LAMPORTS_MASK ,
893+ borrow_bitmask : LAMPORTS_MUTABLE_BORROW_BITMASK ,
877894 // borrow state must be a mutable reference
878895 state : NonNull :: from ( & mut state) ,
879896 marker : PhantomData ,
0 commit comments