|
| 1 | +use crate::field::Subplace; |
| 2 | + |
| 3 | +/// Marks a type as containing a place. |
| 4 | +/// |
| 5 | +/// This is the new trait for the dereference operator `*`; implementing it will allow writing `*x` |
| 6 | +/// for `x: Self`, but not enable any operations on `*x`. For those, one of the other place |
| 7 | +/// operation traits has to be implemented: |
| 8 | +/// |
| 9 | +/// - [`PlaceRead`] |
| 10 | +/// - [`PlaceWrite`] |
| 11 | +/// - [`PlaceDrop`] |
| 12 | +/// - [`PlaceMove`] |
| 13 | +/// - [`PlaceBorrow`] |
| 14 | +/// - [`PlaceDeref`] |
| 15 | +#[unstable(feature = "field_projections", issue = "145383")] |
| 16 | +#[lang = "place"] |
| 17 | +pub trait Place { |
| 18 | + /// The type of the contained place. |
| 19 | + #[lang = "place_target"] |
| 20 | + type Target: ?Sized; |
| 21 | +} |
| 22 | + |
| 23 | +/// Reading a place `let val = *x;`. |
| 24 | +/// |
| 25 | +/// When `x: Self`, then `let val = *x;` will be desugared into [`PlaceRead::read`]. |
| 26 | +/// |
| 27 | +/// # Safety |
| 28 | +/// |
| 29 | +/// FIXME |
| 30 | +#[unstable(feature = "field_projections", issue = "145383")] |
| 31 | +#[lang = "place_read"] |
| 32 | +pub unsafe trait PlaceRead<S>: Place |
| 33 | +where |
| 34 | + S: Subplace<Source = Self::Target>, |
| 35 | + S::Target: Sized, |
| 36 | +{ |
| 37 | + /// Whether the read operation is safe when used through the operator. |
| 38 | + /// |
| 39 | + /// When the compiler emits the call to `read`, the borrow checker guarantees that no other |
| 40 | + /// operation is conflicting with this one. |
| 41 | + #[lang = "place_read_safety"] |
| 42 | + const SAFETY: bool; |
| 43 | + |
| 44 | + /// Reads the subplace pointed to by `this`. |
| 45 | + /// |
| 46 | + /// # Safety |
| 47 | + /// |
| 48 | + /// FIXME |
| 49 | + #[lang = "place_read_read"] |
| 50 | + unsafe fn read(this: *const Self, sub: S) -> S::Target; |
| 51 | +} |
| 52 | + |
| 53 | +/// Writing a place `*x = val;`. |
| 54 | +/// |
| 55 | +/// When `x: Self`, then `*x = val;` will be desugared into [`PlaceWrite::write`]. |
| 56 | +/// |
| 57 | +/// # Safety |
| 58 | +/// |
| 59 | +/// FIXME |
| 60 | +#[unstable(feature = "field_projections", issue = "145383")] |
| 61 | +#[lang = "place_write"] |
| 62 | +pub unsafe trait PlaceWrite<S>: Place |
| 63 | +where |
| 64 | + S: Subplace<Source = Self::Target>, |
| 65 | + S::Target: Sized, |
| 66 | +{ |
| 67 | + /// Whether the write operation is safe when used through the operator. |
| 68 | + /// |
| 69 | + /// When the compiler emits the call to `read`, the borrow checker guarantees that no other |
| 70 | + /// operation is conflicting with this one. |
| 71 | + #[lang = "place_write_safety"] |
| 72 | + const SAFETY: bool; |
| 73 | + |
| 74 | + /// Writes to the subplace pointed to by `this`. |
| 75 | + /// |
| 76 | + /// # Safety |
| 77 | + /// |
| 78 | + /// FIXME |
| 79 | + #[lang = "place_write_write"] |
| 80 | + unsafe fn write(this: *const Self, sub: S, value: S::Target); |
| 81 | +} |
| 82 | + |
| 83 | +/// Moving out of a place. |
| 84 | +/// |
| 85 | +/// When `x: Self` and one performs a [`PlaceRead::read`] where the target value is not [`Copy`], |
| 86 | +/// then the compiler checks if this trait is implemented and if so, moves the value out by reading |
| 87 | +/// it and adjusting the borrow checker state of the place. |
| 88 | +/// |
| 89 | +/// # Safety |
| 90 | +/// |
| 91 | +/// FIXME |
| 92 | +#[unstable(feature = "field_projections", issue = "145383")] |
| 93 | +#[lang = "place_move"] |
| 94 | +pub unsafe trait PlaceMove<S>: PlaceRead<S> |
| 95 | +where |
| 96 | + S: Subplace<Source = Self::Target>, |
| 97 | + S::Target: Sized, |
| 98 | +{ |
| 99 | +} |
| 100 | + |
| 101 | +/// Dropping a place. |
| 102 | +/// |
| 103 | +/// Emitted by the compiler when a place has been partially moved out and the pointer with ownership |
| 104 | +/// is being dropped. |
| 105 | +/// |
| 106 | +/// # Safety |
| 107 | +/// |
| 108 | +/// FIXME |
| 109 | +#[unstable(feature = "field_projections", issue = "145383")] |
| 110 | +#[lang = "place_drop"] |
| 111 | +pub unsafe trait PlaceDrop<S>: Place |
| 112 | +where |
| 113 | + S: Subplace<Source = Self::Target>, |
| 114 | +{ |
| 115 | + /// Drop the subplace pointed to by `this`. |
| 116 | + /// |
| 117 | + /// # Safety |
| 118 | + /// |
| 119 | + /// FIXME |
| 120 | + #[lang = "place_drop_drop"] |
| 121 | + unsafe fn drop(this: *const Self, sub: S); |
| 122 | +} |
| 123 | + |
| 124 | +/// Dropping a pointer that points at a fully moved-out place. |
| 125 | +/// |
| 126 | +/// This operation is emitted by the compiler when a pointer is being dropped that had some fields |
| 127 | +/// moved out. |
| 128 | +/// |
| 129 | +/// # Safety |
| 130 | +/// |
| 131 | +/// FIXME |
| 132 | +#[unstable(feature = "field_projections", issue = "145383")] |
| 133 | +#[lang = "drop_husk"] |
| 134 | +pub unsafe trait DropHusk: Place { |
| 135 | + /// Drops the |
| 136 | + /// |
| 137 | + /// # Safety |
| 138 | + /// |
| 139 | + /// FIXME |
| 140 | + #[lang = "drop_husk_drop_husk"] |
| 141 | + unsafe fn drop_husk(this: *const Self); |
| 142 | +} |
| 143 | + |
| 144 | +/// Borrowing a place with `X`. |
| 145 | +/// |
| 146 | +/// When `y: Self`, then `let x = @<X> *y;` will be desugared into [`PlaceBorrow::borrow`]. |
| 147 | +/// |
| 148 | +/// # Safety |
| 149 | +/// |
| 150 | +/// FIXME |
| 151 | +#[unstable(feature = "field_projections", issue = "145383")] |
| 152 | +#[lang = "place_borrow"] |
| 153 | +pub unsafe trait PlaceBorrow<S, X>: Place |
| 154 | +where |
| 155 | + S: Subplace<Source = Self::Target>, |
| 156 | + X: Place<Target = S::Target>, |
| 157 | +{ |
| 158 | + /// Whether the borrow operation is safe when used through the operator. |
| 159 | + /// |
| 160 | + /// When the compiler emits the call to `read`, the borrow checker guarantees that no other |
| 161 | + /// operation is conflicting with this one. |
| 162 | + #[lang = "place_borrow_safety"] |
| 163 | + const SAFETY: bool; |
| 164 | + |
| 165 | + /// Borrow the subplace pointed to by `this` with `X`. |
| 166 | + /// |
| 167 | + /// # Safety |
| 168 | + /// |
| 169 | + /// FIXME |
| 170 | + #[lang = "place_borrow_borrow"] |
| 171 | + unsafe fn borrow(this: *const Self, sub: S) -> X; |
| 172 | +} |
| 173 | + |
| 174 | +/// Accessing a nested pointer. |
| 175 | +/// |
| 176 | +/// When `x: Self`, then nested dereferences `let _ = **x;` is desugared into a combination of the |
| 177 | +/// corresponding operation and a [`PlaceDeref::deref`]. |
| 178 | +/// |
| 179 | +/// # Safety |
| 180 | +/// |
| 181 | +/// FIXME |
| 182 | +#[unstable(feature = "field_projections", issue = "145383")] |
| 183 | +#[lang = "place_deref"] |
| 184 | +pub unsafe trait PlaceDeref<S>: Place |
| 185 | +where |
| 186 | + S: Subplace<Source = Self::Target>, |
| 187 | + S::Target: Place, |
| 188 | +{ |
| 189 | + /// Obtain a raw pointer to the subplace pointed to by `this`. |
| 190 | + /// |
| 191 | + /// # Safety |
| 192 | + /// |
| 193 | + /// FIXME |
| 194 | + #[lang = "place_deref_deref"] |
| 195 | + unsafe fn deref(this: *const Self, sub: S) -> *const S::Target; |
| 196 | +} |
| 197 | + |
| 198 | +/// Forwards the subplace `S` of the place contained by this. |
| 199 | +/// |
| 200 | +/// When `x: Self` and `Self::Target` has a subplace `S` accessible via `.foo.bar`, then `x.foo.bar` |
| 201 | +/// is also valid, has type `<Self::Wrapped as Subplace>::Target` and any place operation on it uses |
| 202 | +/// <code>[Self::wrap]\(sub\)</code> as the subplace instead of `S`. |
| 203 | +/// |
| 204 | +/// # Safety |
| 205 | +/// |
| 206 | +/// FIXME |
| 207 | +#[unstable(feature = "field_projections", issue = "145383")] |
| 208 | +#[lang = "place_wrapper"] |
| 209 | +pub unsafe trait PlaceWrapper<S>: Place |
| 210 | +where |
| 211 | + S: Subplace<Source = Self::Target>, |
| 212 | +{ |
| 213 | + /// The subplace to use instead of `S` for any place operations on `Self`. |
| 214 | + #[lang = "place_wrapper_wrapped"] |
| 215 | + type Wrapped: Subplace<Source = Self>; |
| 216 | + |
| 217 | + /// Turn a subplace of type `S` into [`Self::Wrapped`]. |
| 218 | + #[lang = "place_wrapper_wrap"] |
| 219 | + fn wrap(sub: S) -> Self::Wrapped; |
| 220 | +} |
0 commit comments