Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Teach transmute_{ref,mut}! to handle slice DSTs #2428

Open
wants to merge 1 commit into
base: I691b42ce8c0c3c6e5990e7684fc66f8f5dd73d85
Choose a base branch
from

Conversation

joshlf
Copy link
Member

@joshlf joshlf commented Mar 7, 2025

TODO:

  • Convince ourselves that it's acceptable to drop the TransmuteFrom: SizeCompatible super-trait bound.
  • Write Kani tests for layout computations
  • Print useful error message when try_compute_cast_params fails during
    static assertion
  • Test when post padding doesn't match between types
  • Do we need to prevent the padded size from increasing? While it's not
    a problem on today's Rust, it would become a problem if unsized locals
    are ever introduced, as you could then do *dst = ..., which would
    have the effect of writing padding past the end of *src

Makes progress on #1817

Co-authored-by: Jack Wrenn [email protected]


This PR is on branch cell-traits.

@joshlf joshlf force-pushed the Ib4bc62202e0b3b09d155333b525087f7aa8f02c2 branch 6 times, most recently from 829b199 to a7c40db Compare March 8, 2025 16:58
@joshlf joshlf force-pushed the I70d5aa5ace6bd2e39e679eac7f00a66d4b843d57 branch from 4d09d7c to f2ec335 Compare March 8, 2025 16:58
Base automatically changed from I70d5aa5ace6bd2e39e679eac7f00a66d4b843d57 to main March 8, 2025 19:16
@joshlf joshlf force-pushed the Ib4bc62202e0b3b09d155333b525087f7aa8f02c2 branch 3 times, most recently from 98bbab7 to 5196fac Compare March 9, 2025 01:10
/// constructed using the address of `src` and using `dst_meta` as its
/// pointer metadata, then `dst` will address the same bytes as `src`.
///
/// TODO: Mention that post-padding may not be preserved.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

//
// (15) `dst_len = src_len`
//
// [1] TODO
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

//
// [1] TODO
//
// TODO: Clarify that this algorithm is agnostic to post-padding, and
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

#[allow(clippy::arithmetic_side_effects)]
let elem_multiple = slf.elem_size / other.elem_size;

// INVARIANTS: TODO
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

$crate::util::macro_util::must_use(u)
use $crate::util::macro_util::TransmuteRefDst;
let t = $crate::util::macro_util::Wrap(e);
// SAFETY: todo
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

// SAFETY: TODO
unsafe_impl_for_transparent_wrapper!(T: ?Sized => $dst<T>);

// SAFETY: TODO
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

// SAFETY: TODO
unsafe impl<T: ?Sized> InvariantsEq<$src<T>> for T {}

// SAFETY: TODO
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

// SAFETY: TODO
unsafe impl<T: ?Sized> InvariantsEq<$dst<T>> for T {}

// SAFETY: TODO
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

impl_for_transmute_from!(U: ?Sized + FromZeros => FromZeros for $dst<U>[<U>]);
impl_for_transmute_from!(U: ?Sized + IntoBytes => IntoBytes for $dst<U>[<U>]);

// SAFETY: TODO
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

// SAFETY: TODO
unsafe_impl!(T: ?Sized + Immutable => Immutable for $src<T>);

// SAFETY: TODO
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

@joshlf joshlf force-pushed the Ib4bc62202e0b3b09d155333b525087f7aa8f02c2 branch 2 times, most recently from 398966d to 976b234 Compare March 9, 2025 03:03
@joshlf joshlf changed the base branch from main to I691b42ce8c0c3c6e5990e7684fc66f8f5dd73d85 March 9, 2025 03:03
@joshlf joshlf force-pushed the Ib4bc62202e0b3b09d155333b525087f7aa8f02c2 branch 3 times, most recently from 8634aa4 to bd3b50a Compare March 9, 2025 06:43
TODO:
- Convince ourselves that it's acceptable to drop the `TransmuteFrom:
  SizeCompatible` super-trait bound.
- Write Kani tests for layout computations
- Print useful error message when `try_compute_cast_params` fails during
  static assertion
- Test when post padding doesn't match between types
- Do we need to prevent the padded size from increasing? While it's not
  a problem on today's Rust, it would become a problem if unsized locals
  are ever introduced, as you could then do `*dst = ...`, which would
  have the effect of writing padding past the end of `*src`

Makes progress on #1817

Co-authored-by: Jack Wrenn <[email protected]>
gherrit-pr-id: Ib4bc62202e0b3b09d155333b525087f7aa8f02c2
@joshlf joshlf force-pushed the Ib4bc62202e0b3b09d155333b525087f7aa8f02c2 branch from bd3b50a to e972a2c Compare March 9, 2025 06:47
Comment on lines +284 to +295
/// For all [valid sizes] of `Src`, `ssize`, the following must hold:
///
/// Let `dsize` be the smallest valid size of `Dst` such that `dsize >=
/// ssize`.\* For all `DV`-valid values of `Dst` with size `dsize`, `dst`, and
/// for all `SV`-valid values of `Src` with size `ssize`, `src`, let `dst'` be
/// constructed by concatenating `src` with the trailing `dsize - ssize` bytes
/// of `dst`. It must be the case that `dst'` is a `DV`-valid `Dst`.
///
/// Now, instead let `dsize` be the largest valid size of `Dst` such that `dsize
/// <= ssize`.\* For all `SV`-valid values of `Src` with size `ssize`, `src`, it
/// must be the case that the leading `dsize` bytes of `src` constitute a
/// `DV`-valid `Dst`.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The motivation behind this invariant is case analysis:

  • When going from &Src to &Dst, we require that ssize >= dsize, or else we'd produce a &Dst that addresses bytes past the end of the original referent. So long as we always implement such transmutes by choosing the largest dsize such that dsize <= ssize, then the second condition ensures that this is sound.
  • If we have already gone from &mut Dst to &mut Src (or & with interior mutation), then we need it to be the case that writing a src to this reference will not invalidate the original Dst. Again, so long as we always implement reference transmutes by choosing the largest possible valid size for the produced reference, then the first condition ensures that it is sound for the resulting &mut Src to be modified, overwriting the prefix of Dst.

My intention is that this should handle by-reference transmutations for all four combinations of sized or unsized Src to sized or unsized Dst:

  • Unsized to unsized is the fully general case described by this prose.
  • Sized to unsized means that there's exactly one value of ssize, but the subsequent condition still needs to hold (regarding the largest and smallest values of dsize on either size of ssize).
  • Unsized to sized means that there's exactly one value of dsize to consider in the analysis
    • For all values of ssize such that dsize <= ssize, we consider truncating transmutes
    • For all values of ssize such that dsize >= ssize, we consider tearing transmutes
  • Sized to sized is trivial, since there are no "foralls" or "there exists" involved. There are again two sub-cases:
    • If dsize <= ssize, we must consider truncating transmutes
    • If dsize >= ssize, we must consider tearing transmutes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant