|
184 | 184 | //! provide a safe interface on top.
|
185 | 185 | //!
|
186 | 186 | //! There are a couple of linked disadvantages to using this model. The core issue is a lack
|
187 |
| -//! of generality. This is an issue first because it means hat each individual type that |
188 |
| -//! implements such an interface does so on its own. Each individual developer must themselves |
189 |
| -//! think through all the guarantees needed to ensure the API they present is sound. This puts |
190 |
| -//! a greater burden on each developer, rather than allowing building a shared understanding of the |
191 |
| -//! problem space, encoded into a shared interface to solve it. In addition, and the key issue that |
192 |
| -//! drove Rust towards another solution, is that each individual object must assume it is on its |
193 |
| -//! own in ensuring that its data does not become *moved* or otherwise invalidated. Since there is |
194 |
| -//! no shared contract between values of different types, an object cannot assume that others |
195 |
| -//! interacting with it will be a good citizen with its data. Because of this, *composition* of |
196 |
| -//! address-sensitive types requires at least a level of pointer indirection (and, practically, a |
197 |
| -//! heap allocation) each time a new object is added to the mix. This is particularly a problem |
198 |
| -//! when one considers the implications of composing together the [`Future`]s which will eventaully |
199 |
| -//! make up an asynchronous task (including address-sensitive `async fn` state machines). |
200 |
| -//! It is plausible that there could be many layers of [`Future`]s composed together, including |
201 |
| -//! multiple layers of `async fn`s handling different parts of a task, and it was deemed |
202 |
| -//! unacceptable to force indirection and allocation for each layer of composition in this case. |
| 187 | +//! of generality. This is an issue because it means that each individual type that implements |
| 188 | +//! such an interface does so on its own. Each developer implementing such a type must themselves |
| 189 | +//! think through all the guarantees needed to ensure the API they present is sound. We would |
| 190 | +//! rather build a shared understanding of the problem space and encode that understanding into a |
| 191 | +//! shared interface to solve it which everyone helps validate. |
| 192 | +//! |
| 193 | +//! In addition, and the key issue that drove Rust towards developing another solution, is that |
| 194 | +//! in this model, each individual object must assume it is *on its own* to ensure that its data |
| 195 | +//! does not become *moved* or otherwise invalidated. Since there is no shared contract between |
| 196 | +//! values of different types, an object cannot assume that others interacting with it will |
| 197 | +//! properly respect the invariants around interacting with its data and must therefore protect |
| 198 | +//! it from everyone. Because of this, *composition* of address-sensitive types requires at least |
| 199 | +//! a level of pointer indirection each time a new object is added to the mix (and, practically, a |
| 200 | +//! heap allocation). |
| 201 | +//! |
| 202 | +//! This is particularly a problem when one considers, for exapmle, the implications of composing |
| 203 | +//! together the [`Future`]s which will eventaully make up an asynchronous task (including |
| 204 | +//! address-sensitive `async fn` state machines). It is plausible that there could be many layers |
| 205 | +//! of [`Future`]s composed together, including multiple layers of `async fn`s handling different |
| 206 | +//! parts of a task. It was deemed unacceptable to force indirection and allocation for each layer |
| 207 | +//! of composition in this case. |
203 | 208 | //!
|
204 | 209 | //! [`Pin<Ptr>`] is an implementation of the third option. It allows us to solve the issues
|
205 | 210 | //! discussed with the second option by building a *shared contractual language* around the
|
|
0 commit comments