annotate rust/hg-core/src/dirstate_tree/owning.rs @ 48999:cfd270d83169 stable

rust: explain why the current `OwningDirstateMap` is unsound See inline comments. Differential Revision: https://phab.mercurial-scm.org/D12428
author Rapha?l Gom?s <rgomes@octobus.net>
date Tue, 05 Apr 2022 10:55:27 +0200
parents d1210d56008b
children dd6b67d5c256
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
1 use super::dirstate_map::DirstateMap;
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
2 use stable_deref_trait::StableDeref;
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
3 use std::ops::Deref;
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
4
48999
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
5 /*
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
6 // /!\ This is unsound and can cause use after free. It will be fixed in the
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
7 // next patch
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
8
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
9 // If we change `value` from its current use of `HgPathBuf` to `&HgPath`,
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
10 // nothing here tells that `value` will outlive `OwningDirstateMap`
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
11 pub fn copy_map_insert<'a,'owned>(
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
12 &'owned mut self,
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
13 key: &HgPath,
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
14 value: &'a HgPath,
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
15 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> {
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
16 // `'local` is smaller than `'a` here
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
17 let map: &'local mut DirstateMap<'local> = self.get_map_mut();
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
18 let node: &'local mut Node<'local> = DirstateMap::get_or_insert_node(
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
19 map.on_disk,
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
20 &mut map.unreachable_bytes,
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
21 &mut map.root,
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
22 &key,
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
23 WithBasename::to_cow_owned,
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
24 |_ancestor| {},
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
25 )?;
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
26 if node.copy_source.is_none() {
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
27 map.nodes_with_copy_source_count += 1
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
28 }
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
29 Ok(node.copy_source.replace(value.into()).map(Cow::into_owned))
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
30 // and right here ----------^^^^^^^^^^^^
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
31 // we are storing `&'a HgPath` in `Node<'local>` which is possible
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
32 // because to the compiler, `'a` is longer than ``local`.
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
33 // It is wrong because nothing proves that `&'a HgPath` will outlive `self`.
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
34 }
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
35
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
36 // All of this is caused by the wrong cast of the DirstateMap pointer that
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
37 // fakes the lifetime of `DirstateMap` and ensures the compiler that it lives
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
38 // as long as `on_disk`, which is only true for its immutable data.
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
39 // This will be fixed in the next commit.
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
40 */
cfd270d83169 rust: explain why the current `OwningDirstateMap` is unsound
Rapha?l Gom?s <rgomes@octobus.net>
parents: 48567
diff changeset
41
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
42 /// Keep a `DirstateMap<'on_disk>` next to the `on_disk` buffer that it
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
43 /// borrows.
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
44 ///
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
45 /// This is similar to [`OwningRef`] which is more limited because it
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
46 /// represents exactly one `&T` reference next to the value it borrows, as
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
47 /// opposed to a struct that may contain an arbitrary number of references in
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
48 /// arbitrarily-nested data structures.
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
49 ///
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
50 /// [`OwningRef`]: https://docs.rs/owning_ref/0.4.1/owning_ref/struct.OwningRef.html
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
51 pub struct OwningDirstateMap {
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
52 /// Owned handle to a bytes buffer with a stable address.
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
53 ///
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
54 /// See <https://docs.rs/owning_ref/0.4.1/owning_ref/trait.StableAddress.html>.
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
55 on_disk: Box<dyn Deref<Target = [u8]> + Send>,
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
56
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
57 /// Pointer for `Box<DirstateMap<'on_disk>>`, typed-erased because the
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
58 /// language cannot represent a lifetime referencing a sibling field.
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
59 /// This is not quite a self-referencial struct (moving this struct is not
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
60 /// a problem as it doesn’t change the address of the bytes buffer owned
48567
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
61 /// by `on_disk`) but touches similar borrow-checker limitations.
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
62 ptr: *mut (),
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
63 }
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
64
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
65 impl OwningDirstateMap {
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
66 pub fn new_empty<OnDisk>(on_disk: OnDisk) -> Self
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
67 where
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
68 OnDisk: Deref<Target = [u8]> + StableDeref + Send + 'static,
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
69 {
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
70 let on_disk = Box::new(on_disk);
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
71 let bytes: &'_ [u8] = &on_disk;
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
72 let map = DirstateMap::empty(bytes);
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
73
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
74 // Like in `bytes` above, this `'_` lifetime parameter borrows from
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
75 // the bytes buffer owned by `on_disk`.
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
76 let ptr: *mut DirstateMap<'_> = Box::into_raw(Box::new(map));
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
77
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
78 // Erase the pointed type entirely in order to erase the lifetime.
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
79 let ptr: *mut () = ptr.cast();
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
80
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
81 Self { on_disk, ptr }
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
82 }
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
83
48069
3d0a9c6e614d dirstate: Remove the Rust abstraction DirstateMapMethods
Simon Sapin <simon.sapin@octobus.net>
parents: 48041
diff changeset
84 pub fn get_pair_mut<'a>(
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
85 &'a mut self,
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
86 ) -> (&'a [u8], &'a mut DirstateMap<'a>) {
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
87 // SAFETY: We cast the type-erased pointer back to the same type it had
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
88 // in `new`, except with a different lifetime parameter. This time we
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
89 // connect the lifetime to that of `self`. This cast is valid because
48567
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
90 // `self` owns the same `on_disk` whose buffer `DirstateMap`
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
91 // references. That buffer has a stable memory address because our
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
92 // `Self::new_empty` counstructor requires `StableDeref`.
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
93 let ptr: *mut DirstateMap<'a> = self.ptr.cast();
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
94 // SAFETY: we dereference that pointer, connecting the lifetime of the
48567
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
95 // new `&mut` to that of `self`. This is valid because the
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
96 // raw pointer is to a boxed value, and `self` owns that box.
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
97 (&self.on_disk, unsafe { &mut *ptr })
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
98 }
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
99
48069
3d0a9c6e614d dirstate: Remove the Rust abstraction DirstateMapMethods
Simon Sapin <simon.sapin@octobus.net>
parents: 48041
diff changeset
100 pub fn get_map_mut<'a>(&'a mut self) -> &'a mut DirstateMap<'a> {
3d0a9c6e614d dirstate: Remove the Rust abstraction DirstateMapMethods
Simon Sapin <simon.sapin@octobus.net>
parents: 48041
diff changeset
101 self.get_pair_mut().1
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
102 }
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
103
48069
3d0a9c6e614d dirstate: Remove the Rust abstraction DirstateMapMethods
Simon Sapin <simon.sapin@octobus.net>
parents: 48041
diff changeset
104 pub fn get_map<'a>(&'a self) -> &'a DirstateMap<'a> {
48567
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
105 // SAFETY: same reasoning as in `get_pair_mut` above.
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
106 let ptr: *mut DirstateMap<'a> = self.ptr.cast();
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
107 unsafe { &*ptr }
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
108 }
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
109
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
110 pub fn on_disk<'a>(&'a self) -> &'a [u8] {
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
111 &self.on_disk
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
112 }
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
113 }
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
114
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
115 impl Drop for OwningDirstateMap {
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
116 fn drop(&mut self) {
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
117 // Silence a "field is never read" warning, and demonstrate that this
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
118 // value is still alive.
48567
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
119 let _: &Box<dyn Deref<Target = [u8]> + Send> = &self.on_disk;
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
120 // SAFETY: this cast is the same as in `get_mut`, and is valid for the
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
121 // same reason. `self.on_disk` still exists at this point, drop glue
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
122 // will drop it implicitly after this `drop` method returns.
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
123 let ptr: *mut DirstateMap<'_> = self.ptr.cast();
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
124 // SAFETY: `Box::from_raw` takes ownership of the box away from `self`.
48567
d1210d56008b rust: Fix outdated comments in OwningDirstateMap
Simon Sapin <simon.sapin@octobus.net>
parents: 48069
diff changeset
125 // This is fine because drop glue does nothing for `*mut ()` and we’re
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
126 // in `drop`, so `get` and `get_mut` cannot be called again.
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
127 unsafe { drop(Box::from_raw(ptr)) }
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
128 }
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
129 }
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
130
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
131 fn _static_assert_is_send<T: Send>() {}
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
132
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
133 fn _static_assert_fields_are_send() {
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
134 _static_assert_is_send::<Box<DirstateMap<'_>>>();
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
135 }
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
136
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
137 // SAFETY: we don’t get this impl implicitly because `*mut (): !Send` because
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
138 // thread-safety of raw pointers is unknown in the general case. However this
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
139 // particular raw pointer represents a `Box<DirstateMap<'on_disk>>` that we
47954
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
140 // own. Since that `Box` is `Send` as shown in above, it is sound to mark
4afd6cc447b9 rust: Make OwningDirstateMap generic and move it into hg-core
Simon Sapin <simon.sapin@octobus.net>
parents: 47682
diff changeset
141 // this struct as `Send` too.
47123
d8ac62374943 dirstate-tree: Make `DirstateMap` borrow from a bytes buffer
Simon Sapin <simon.sapin@octobus.net>
parents:
diff changeset
142 unsafe impl Send for OwningDirstateMap {}