@@ -570,20 +570,31 @@ impl Display for BorrowMutError {
570570 }
571571}
572572
573- // Values [1, MIN_WRITING-1] represent the number of `Ref` active. Values in
574- // [MIN_WRITING, MAX-1] represent the number of `RefMut` active. Multiple
575- // `RefMut`s can only be active at a time if they refer to distinct,
576- // nonoverlapping components of a `RefCell` (e.g., different ranges of a slice).
573+ // Positive values represent the number of `Ref` active. Negative values
574+ // represent the number of `RefMut` active. Multiple `RefMut`s can only be
575+ // active at a time if they refer to distinct, nonoverlapping components of a
576+ // `RefCell` (e.g., different ranges of a slice).
577577//
578578// `Ref` and `RefMut` are both two words in size, and so there will likely never
579579// be enough `Ref`s or `RefMut`s in existence to overflow half of the `usize`
580- // range. Thus, a `BorrowFlag` will probably never overflow. However, this is
581- // not a guarantee, as a pathological program could repeatedly create and then
582- // mem::forget `Ref`s or `RefMut`s. Thus, all code must explicitly check for
583- // overflow in order to avoid unsafety.
584- type BorrowFlag = usize ;
580+ // range. Thus, a `BorrowFlag` will probably never overflow or underflow.
581+ // However, this is not a guarantee, as a pathological program could repeatedly
582+ // create and then mem::forget `Ref`s or `RefMut`s. Thus, all code must
583+ // explicitly check for overflow and underflow in order to avoid unsafety, or at
584+ // least behave correctly in the event that overflow or underflow happens (e.g.,
585+ // see BorrowRef::new).
586+ type BorrowFlag = isize ;
585587const UNUSED : BorrowFlag = 0 ;
586- const MIN_WRITING : BorrowFlag = ( !0 ) /2 + 1 ; // 0b1000...
588+
589+ #[ inline( always) ]
590+ fn is_writing ( x : BorrowFlag ) -> bool {
591+ x < UNUSED
592+ }
593+
594+ #[ inline( always) ]
595+ fn is_reading ( x : BorrowFlag ) -> bool {
596+ x > UNUSED
597+ }
587598
588599impl < T > RefCell < T > {
589600 /// Creates a new `RefCell` containing `value`.
@@ -1022,12 +1033,11 @@ impl<'b> BorrowRef<'b> {
10221033 #[ inline]
10231034 fn new ( borrow : & ' b Cell < BorrowFlag > ) -> Option < BorrowRef < ' b > > {
10241035 let b = borrow. get ( ) ;
1025- if b >= MIN_WRITING {
1036+ if is_writing ( b) || b == isize:: max_value ( ) {
1037+ // If there's currently a writing borrow, or if incrementing the
1038+ // refcount would overflow into a writing borrow.
10261039 None
10271040 } else {
1028- // Prevent the borrow counter from overflowing into
1029- // a writing borrow.
1030- assert ! ( b < MIN_WRITING - 1 ) ;
10311041 borrow. set ( b + 1 ) ;
10321042 Some ( BorrowRef { borrow } )
10331043 }
@@ -1038,7 +1048,7 @@ impl<'b> Drop for BorrowRef<'b> {
10381048 #[ inline]
10391049 fn drop ( & mut self ) {
10401050 let borrow = self . borrow . get ( ) ;
1041- debug_assert ! ( borrow < MIN_WRITING && borrow != UNUSED ) ;
1051+ debug_assert ! ( is_reading ( borrow) ) ;
10421052 self . borrow . set ( borrow - 1 ) ;
10431053 }
10441054}
@@ -1047,12 +1057,12 @@ impl<'b> Clone for BorrowRef<'b> {
10471057 #[ inline]
10481058 fn clone ( & self ) -> BorrowRef < ' b > {
10491059 // Since this Ref exists, we know the borrow flag
1050- // is not set to WRITING .
1060+ // is a reading borrow .
10511061 let borrow = self . borrow . get ( ) ;
1052- debug_assert ! ( borrow != UNUSED ) ;
1062+ debug_assert ! ( is_reading ( borrow) ) ;
10531063 // Prevent the borrow counter from overflowing into
10541064 // a writing borrow.
1055- assert ! ( borrow < MIN_WRITING - 1 ) ;
1065+ assert ! ( borrow != isize :: max_value ( ) ) ;
10561066 self . borrow . set ( borrow + 1 ) ;
10571067 BorrowRef { borrow : self . borrow }
10581068 }
@@ -1251,12 +1261,8 @@ impl<'b> Drop for BorrowRefMut<'b> {
12511261 #[ inline]
12521262 fn drop ( & mut self ) {
12531263 let borrow = self . borrow . get ( ) ;
1254- debug_assert ! ( borrow >= MIN_WRITING ) ;
1255- self . borrow . set ( if borrow == MIN_WRITING {
1256- UNUSED
1257- } else {
1258- borrow - 1
1259- } ) ;
1264+ debug_assert ! ( is_writing( borrow) ) ;
1265+ self . borrow . set ( borrow + 1 ) ;
12601266 }
12611267}
12621268
@@ -1266,10 +1272,10 @@ impl<'b> BorrowRefMut<'b> {
12661272 // NOTE: Unlike BorrowRefMut::clone, new is called to create the initial
12671273 // mutable reference, and so there must currently be no existing
12681274 // references. Thus, while clone increments the mutable refcount, here
1269- // we simply go directly from UNUSED to MIN_WRITING .
1275+ // we explicitly only allow going from UNUSED to UNUSED - 1 .
12701276 match borrow. get ( ) {
12711277 UNUSED => {
1272- borrow. set ( MIN_WRITING ) ;
1278+ borrow. set ( UNUSED - 1 ) ;
12731279 Some ( BorrowRefMut { borrow : borrow } )
12741280 } ,
12751281 _ => None ,
@@ -1284,10 +1290,10 @@ impl<'b> BorrowRefMut<'b> {
12841290 #[ inline]
12851291 fn clone ( & self ) -> BorrowRefMut < ' b > {
12861292 let borrow = self . borrow . get ( ) ;
1287- debug_assert ! ( borrow >= MIN_WRITING ) ;
1288- // Prevent the borrow counter from overflowing .
1289- assert ! ( borrow != ! 0 ) ;
1290- self . borrow . set ( borrow + 1 ) ;
1293+ debug_assert ! ( is_writing ( borrow) ) ;
1294+ // Prevent the borrow counter from underflowing .
1295+ assert ! ( borrow != isize :: min_value ( ) ) ;
1296+ self . borrow . set ( borrow - 1 ) ;
12911297 BorrowRefMut { borrow : self . borrow }
12921298 }
12931299}
0 commit comments