Make errors witnesses to a cast's source type
- Dominant language
- Rust
- Stars
- 2.6k
- Forks
- 179
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 29
Description
## Design
### Problem statement
Our errors currently store the source value of any cast or conversion. We also permit the user to discard this value via `.map_src` methods, which is sometimes necessary in order to play nicely with APIs that require errors to be `'static`, `Send`, or `Sync`.
However, we've also discussed supporting #280 by doing the opposite: by *preventing* the user from discarding the source, we can use an error object as a witness that an error was encountered *with a particular source type*, and thus as a witness that certain failure modes are impossible (in particular, when casting from `Src` to `Dst` where `Src` is more aligned than `Dst`, alignment errors are impossible).
### Design
These two goals are at odds, but I think we can reconcile them. We do this by storing both the *original* source type and a source *value*.
```rust
pub struct AlignmentError {
/// The source value involved in the conversion.
src_val: SrcVal,
/// The inner destination type inolved in the conversion.
///
/// INVARIANT: An `AlignmentError` may only be constructed if `Dst`'s
/// alignment requirement is greater `Src`'s alignment requirement.
src_dst: SendSyncPhantomData<(Src, Dst)>,
}
impl AlignmentError {
pub fn map_src(self, f: impl Fn(SrcVal) -> NewSrcVal) -> AlignmentError {
AlignmentError { src_val: f(self.src_val), src_dst: SendSyncPhantomData::default() }
}
}
```
With this change, we can require that both `Src` and `Dst` are the actual types involved in a cast, and thus we can make the internal invariant more powerful. As it stands today, the invariant is that:
https://github.com/google/zerocopy/blob/0b8ad3ea2719acb1485dc1e622926c61dbc7af99/src/error.rs#L237-L238
With this change, we generalize the invariant to require that `Dst`'s alignment is greater than `Src`'s alignment.
### Use
In theory, this should let us infallibly discard alignment errors in more circumstances, generalizing our current support:
https://github.com/google/zerocopy/blob/0b8ad3ea2719acb1485dc1e622926c61dbc7af99/src/error.rs#L720-L769
However, this requires being able to express alignment inequality as a type-level bound (e.g. via #1316), which we don't yet support.
Contributor guide
Assessment
This issue has not been assessed yet.