##// END OF EJS Templates
rust: Fix outdated comments in OwningDirstateMap...
Simon Sapin -
r49416:d1210d56 default
parent child Browse files
Show More
@@ -1,105 +1,105 b''
1 use super::dirstate_map::DirstateMap;
1 use super::dirstate_map::DirstateMap;
2 use stable_deref_trait::StableDeref;
2 use stable_deref_trait::StableDeref;
3 use std::ops::Deref;
3 use std::ops::Deref;
4
4
5 /// Keep a `DirstateMap<'on_disk>` next to the `on_disk` buffer that it
5 /// Keep a `DirstateMap<'on_disk>` next to the `on_disk` buffer that it
6 /// borrows.
6 /// borrows.
7 ///
7 ///
8 /// This is similar to [`OwningRef`] which is more limited because it
8 /// This is similar to [`OwningRef`] which is more limited because it
9 /// represents exactly one `&T` reference next to the value it borrows, as
9 /// represents exactly one `&T` reference next to the value it borrows, as
10 /// opposed to a struct that may contain an arbitrary number of references in
10 /// opposed to a struct that may contain an arbitrary number of references in
11 /// arbitrarily-nested data structures.
11 /// arbitrarily-nested data structures.
12 ///
12 ///
13 /// [`OwningRef`]: https://docs.rs/owning_ref/0.4.1/owning_ref/struct.OwningRef.html
13 /// [`OwningRef`]: https://docs.rs/owning_ref/0.4.1/owning_ref/struct.OwningRef.html
14 pub struct OwningDirstateMap {
14 pub struct OwningDirstateMap {
15 /// Owned handle to a bytes buffer with a stable address.
15 /// Owned handle to a bytes buffer with a stable address.
16 ///
16 ///
17 /// See <https://docs.rs/owning_ref/0.4.1/owning_ref/trait.StableAddress.html>.
17 /// See <https://docs.rs/owning_ref/0.4.1/owning_ref/trait.StableAddress.html>.
18 on_disk: Box<dyn Deref<Target = [u8]> + Send>,
18 on_disk: Box<dyn Deref<Target = [u8]> + Send>,
19
19
20 /// Pointer for `Box<DirstateMap<'on_disk>>`, typed-erased because the
20 /// Pointer for `Box<DirstateMap<'on_disk>>`, typed-erased because the
21 /// language cannot represent a lifetime referencing a sibling field.
21 /// language cannot represent a lifetime referencing a sibling field.
22 /// This is not quite a self-referencial struct (moving this struct is not
22 /// This is not quite a self-referencial struct (moving this struct is not
23 /// a problem as it doesn’t change the address of the bytes buffer owned
23 /// a problem as it doesn’t change the address of the bytes buffer owned
24 /// by `PyBytes`) but touches similar borrow-checker limitations.
24 /// by `on_disk`) but touches similar borrow-checker limitations.
25 ptr: *mut (),
25 ptr: *mut (),
26 }
26 }
27
27
28 impl OwningDirstateMap {
28 impl OwningDirstateMap {
29 pub fn new_empty<OnDisk>(on_disk: OnDisk) -> Self
29 pub fn new_empty<OnDisk>(on_disk: OnDisk) -> Self
30 where
30 where
31 OnDisk: Deref<Target = [u8]> + StableDeref + Send + 'static,
31 OnDisk: Deref<Target = [u8]> + StableDeref + Send + 'static,
32 {
32 {
33 let on_disk = Box::new(on_disk);
33 let on_disk = Box::new(on_disk);
34 let bytes: &'_ [u8] = &on_disk;
34 let bytes: &'_ [u8] = &on_disk;
35 let map = DirstateMap::empty(bytes);
35 let map = DirstateMap::empty(bytes);
36
36
37 // Like in `bytes` above, this `'_` lifetime parameter borrows from
37 // Like in `bytes` above, this `'_` lifetime parameter borrows from
38 // the bytes buffer owned by `on_disk`.
38 // the bytes buffer owned by `on_disk`.
39 let ptr: *mut DirstateMap<'_> = Box::into_raw(Box::new(map));
39 let ptr: *mut DirstateMap<'_> = Box::into_raw(Box::new(map));
40
40
41 // Erase the pointed type entirely in order to erase the lifetime.
41 // Erase the pointed type entirely in order to erase the lifetime.
42 let ptr: *mut () = ptr.cast();
42 let ptr: *mut () = ptr.cast();
43
43
44 Self { on_disk, ptr }
44 Self { on_disk, ptr }
45 }
45 }
46
46
47 pub fn get_pair_mut<'a>(
47 pub fn get_pair_mut<'a>(
48 &'a mut self,
48 &'a mut self,
49 ) -> (&'a [u8], &'a mut DirstateMap<'a>) {
49 ) -> (&'a [u8], &'a mut DirstateMap<'a>) {
50 // SAFETY: We cast the type-erased pointer back to the same type it had
50 // SAFETY: We cast the type-erased pointer back to the same type it had
51 // in `new`, except with a different lifetime parameter. This time we
51 // in `new`, except with a different lifetime parameter. This time we
52 // connect the lifetime to that of `self`. This cast is valid because
52 // connect the lifetime to that of `self`. This cast is valid because
53 // `self` owns the same `PyBytes` whose buffer `DirstateMap`
53 // `self` owns the same `on_disk` whose buffer `DirstateMap`
54 // references. That buffer has a stable memory address because the byte
54 // references. That buffer has a stable memory address because our
55 // string value of a `PyBytes` is immutable.
55 // `Self::new_empty` counstructor requires `StableDeref`.
56 let ptr: *mut DirstateMap<'a> = self.ptr.cast();
56 let ptr: *mut DirstateMap<'a> = self.ptr.cast();
57 // SAFETY: we dereference that pointer, connecting the lifetime of the
57 // SAFETY: we dereference that pointer, connecting the lifetime of the
58 // new `&mut` to that of `self`. This is valid because the
58 // new `&mut` to that of `self`. This is valid because the
59 // raw pointer is to a boxed value, and `self` owns that box.
59 // raw pointer is to a boxed value, and `self` owns that box.
60 (&self.on_disk, unsafe { &mut *ptr })
60 (&self.on_disk, unsafe { &mut *ptr })
61 }
61 }
62
62
63 pub fn get_map_mut<'a>(&'a mut self) -> &'a mut DirstateMap<'a> {
63 pub fn get_map_mut<'a>(&'a mut self) -> &'a mut DirstateMap<'a> {
64 self.get_pair_mut().1
64 self.get_pair_mut().1
65 }
65 }
66
66
67 pub fn get_map<'a>(&'a self) -> &'a DirstateMap<'a> {
67 pub fn get_map<'a>(&'a self) -> &'a DirstateMap<'a> {
68 // SAFETY: same reasoning as in `get_mut` above.
68 // SAFETY: same reasoning as in `get_pair_mut` above.
69 let ptr: *mut DirstateMap<'a> = self.ptr.cast();
69 let ptr: *mut DirstateMap<'a> = self.ptr.cast();
70 unsafe { &*ptr }
70 unsafe { &*ptr }
71 }
71 }
72
72
73 pub fn on_disk<'a>(&'a self) -> &'a [u8] {
73 pub fn on_disk<'a>(&'a self) -> &'a [u8] {
74 &self.on_disk
74 &self.on_disk
75 }
75 }
76 }
76 }
77
77
78 impl Drop for OwningDirstateMap {
78 impl Drop for OwningDirstateMap {
79 fn drop(&mut self) {
79 fn drop(&mut self) {
80 // Silence a "field is never read" warning, and demonstrate that this
80 // Silence a "field is never read" warning, and demonstrate that this
81 // value is still alive.
81 // value is still alive.
82 let _ = &self.on_disk;
82 let _: &Box<dyn Deref<Target = [u8]> + Send> = &self.on_disk;
83 // SAFETY: this cast is the same as in `get_mut`, and is valid for the
83 // SAFETY: this cast is the same as in `get_mut`, and is valid for the
84 // same reason. `self.on_disk` still exists at this point, drop glue
84 // same reason. `self.on_disk` still exists at this point, drop glue
85 // will drop it implicitly after this `drop` method returns.
85 // will drop it implicitly after this `drop` method returns.
86 let ptr: *mut DirstateMap<'_> = self.ptr.cast();
86 let ptr: *mut DirstateMap<'_> = self.ptr.cast();
87 // SAFETY: `Box::from_raw` takes ownership of the box away from `self`.
87 // SAFETY: `Box::from_raw` takes ownership of the box away from `self`.
88 // This is fine because drop glue does nothig for `*mut ()` and we’re
88 // This is fine because drop glue does nothing for `*mut ()` and we’re
89 // in `drop`, so `get` and `get_mut` cannot be called again.
89 // in `drop`, so `get` and `get_mut` cannot be called again.
90 unsafe { drop(Box::from_raw(ptr)) }
90 unsafe { drop(Box::from_raw(ptr)) }
91 }
91 }
92 }
92 }
93
93
94 fn _static_assert_is_send<T: Send>() {}
94 fn _static_assert_is_send<T: Send>() {}
95
95
96 fn _static_assert_fields_are_send() {
96 fn _static_assert_fields_are_send() {
97 _static_assert_is_send::<Box<DirstateMap<'_>>>();
97 _static_assert_is_send::<Box<DirstateMap<'_>>>();
98 }
98 }
99
99
100 // SAFETY: we don’t get this impl implicitly because `*mut (): !Send` because
100 // SAFETY: we don’t get this impl implicitly because `*mut (): !Send` because
101 // thread-safety of raw pointers is unknown in the general case. However this
101 // thread-safety of raw pointers is unknown in the general case. However this
102 // particular raw pointer represents a `Box<DirstateMap<'on_disk>>` that we
102 // particular raw pointer represents a `Box<DirstateMap<'on_disk>>` that we
103 // own. Since that `Box` is `Send` as shown in above, it is sound to mark
103 // own. Since that `Box` is `Send` as shown in above, it is sound to mark
104 // this struct as `Send` too.
104 // this struct as `Send` too.
105 unsafe impl Send for OwningDirstateMap {}
105 unsafe impl Send for OwningDirstateMap {}
General Comments 0
You need to be logged in to leave comments. Login now