Skip to content

Commit e459223

Browse files
authored
Merge pull request #123 from andersk/GcCellRefMut-map
GcCellRefMut::drop: Unroot the right value after GcCellRefMut::map
2 parents 910624b + 98fb0cf commit e459223

File tree

2 files changed

+31
-23
lines changed

2 files changed

+31
-23
lines changed

gc/src/lib.rs

+23-23
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ impl<T: Trace + ?Sized> GcCell<T> {
588588
}
589589

590590
Ok(GcCellRefMut {
591-
flags: &self.flags,
591+
gc_cell: self,
592592
value: &mut *self.cell.get(),
593593
})
594594
}
@@ -795,12 +795,12 @@ impl<'a, T: ?Sized + Display> Display for GcCellRef<'a, T> {
795795
}
796796

797797
/// A wrapper type for a mutably borrowed value from a `GcCell<T>`.
798-
pub struct GcCellRefMut<'a, T: Trace + ?Sized + 'static> {
799-
flags: &'a Cell<BorrowFlag>,
800-
value: &'a mut T,
798+
pub struct GcCellRefMut<'a, T: Trace + ?Sized + 'static, U: ?Sized = T> {
799+
gc_cell: &'a GcCell<T>,
800+
value: &'a mut U,
801801
}
802802

803-
impl<'a, T: Trace + ?Sized> GcCellRefMut<'a, T> {
803+
impl<'a, T: Trace + ?Sized, U: ?Sized> GcCellRefMut<'a, T, U> {
804804
/// Makes a new `GcCellRefMut` for a component of the borrowed data, e.g., an enum
805805
/// variant.
806806
///
@@ -818,22 +818,22 @@ impl<'a, T: Trace + ?Sized> GcCellRefMut<'a, T> {
818818
/// let c = GcCell::new((5, 'b'));
819819
/// {
820820
/// let b1: GcCellRefMut<(u32, char)> = c.borrow_mut();
821-
/// let mut b2: GcCellRefMut<u32> = GcCellRefMut::map(b1, |t| &mut t.0);
821+
/// let mut b2: GcCellRefMut<(u32, char), u32> = GcCellRefMut::map(b1, |t| &mut t.0);
822822
/// assert_eq!(*b2, 5);
823823
/// *b2 = 42;
824824
/// }
825825
/// assert_eq!(*c.borrow(), (42, 'b'));
826826
/// ```
827827
#[inline]
828-
pub fn map<U, F>(orig: Self, f: F) -> GcCellRefMut<'a, U>
828+
pub fn map<V, F>(orig: Self, f: F) -> GcCellRefMut<'a, T, V>
829829
where
830-
U: Trace + ?Sized,
831-
F: FnOnce(&mut T) -> &mut U,
830+
V: ?Sized,
831+
F: FnOnce(&mut U) -> &mut V,
832832
{
833-
let value = unsafe { &mut *(orig.value as *mut T) };
833+
let value = unsafe { &mut *(orig.value as *mut U) };
834834

835835
let ret = GcCellRefMut {
836-
flags: orig.flags,
836+
gc_cell: orig.gc_cell,
837837
value: f(value),
838838
};
839839

@@ -845,44 +845,44 @@ impl<'a, T: Trace + ?Sized> GcCellRefMut<'a, T> {
845845
}
846846
}
847847

848-
impl<'a, T: Trace + ?Sized> Deref for GcCellRefMut<'a, T> {
849-
type Target = T;
848+
impl<'a, T: Trace + ?Sized, U: ?Sized> Deref for GcCellRefMut<'a, T, U> {
849+
type Target = U;
850850

851851
#[inline]
852-
fn deref(&self) -> &T {
852+
fn deref(&self) -> &U {
853853
self.value
854854
}
855855
}
856856

857-
impl<'a, T: Trace + ?Sized> DerefMut for GcCellRefMut<'a, T> {
857+
impl<'a, T: Trace + ?Sized, U: ?Sized> DerefMut for GcCellRefMut<'a, T, U> {
858858
#[inline]
859-
fn deref_mut(&mut self) -> &mut T {
859+
fn deref_mut(&mut self) -> &mut U {
860860
self.value
861861
}
862862
}
863863

864-
impl<'a, T: Trace + ?Sized> Drop for GcCellRefMut<'a, T> {
864+
impl<'a, T: Trace + ?Sized, U: ?Sized> Drop for GcCellRefMut<'a, T, U> {
865865
#[inline]
866866
fn drop(&mut self) {
867-
debug_assert!(self.flags.get().borrowed() == BorrowState::Writing);
867+
debug_assert!(self.gc_cell.flags.get().borrowed() == BorrowState::Writing);
868868
// Restore the rooted state of the GcCell's contents to the state of the GcCell.
869869
// During the lifetime of the GcCellRefMut, the GcCell's contents are rooted.
870-
if !self.flags.get().rooted() {
870+
if !self.gc_cell.flags.get().rooted() {
871871
unsafe {
872-
self.value.unroot();
872+
(*self.gc_cell.cell.get()).unroot();
873873
}
874874
}
875-
self.flags.set(self.flags.get().set_unused());
875+
self.gc_cell.flags.set(self.gc_cell.flags.get().set_unused());
876876
}
877877
}
878878

879-
impl<'a, T: Trace + ?Sized + Debug> Debug for GcCellRefMut<'a, T> {
879+
impl<'a, T: Trace + ?Sized, U: Debug + ?Sized> Debug for GcCellRefMut<'a, T, U> {
880880
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
881881
Debug::fmt(&*(self.deref()), f)
882882
}
883883
}
884884

885-
impl<'a, T: Trace + ?Sized + Display> Display for GcCellRefMut<'a, T> {
885+
impl<'a, T: Trace + ?Sized, U: Display + ?Sized> Display for GcCellRefMut<'a, T, U> {
886886
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
887887
Display::fmt(&**self, f)
888888
}

gc/tests/gc_cell_ref.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use gc::{Gc, GcCell, GcCellRefMut};
2+
3+
#[test]
4+
fn test_gc_cell_ref_mut_map() {
5+
let a = Gc::new(GcCell::new((0, Gc::new(1))));
6+
*GcCellRefMut::map(a.borrow_mut(), |(n, _)| n) = 2;
7+
assert_eq!(a.borrow_mut().0, 2);
8+
}

0 commit comments

Comments
 (0)