Skip to content

Commit 907cbf6

Browse files
committed
[WIP] ReadOnly + is_bit_valid
gherrit-pr-id: I528d60de3bd7f8dcd69986f041f69aad1f890bd0
1 parent c1a3796 commit 907cbf6

File tree

13 files changed

+353
-162
lines changed

13 files changed

+353
-162
lines changed

src/impls.rs

Lines changed: 53 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ use core::{
1313
ptr::NonNull,
1414
};
1515

16+
use crate::pointer::{
17+
invariant::{Initialized, Shared},
18+
SizeEq,
19+
};
20+
1621
use super::*;
1722

1823
// SAFETY: Per the reference [1], "the unit tuple (`()`) ... is guaranteed as a
@@ -105,10 +110,11 @@ assert_unaligned!(bool);
105110
// pattern 0x01.
106111
const _: () = unsafe {
107112
unsafe_impl!(=> TryFromBytes for bool; |byte| {
108-
let byte = byte.transmute::<u8, invariant::Valid, _>();
113+
let byte = byte.transmute::<u8, invariant::Valid, BecauseImmutable>();
109114
*byte.unaligned_as_ref() < 2
110115
})
111116
};
117+
impl_size_eq!(ReadOnly<bool>, u8);
112118
impl_size_eq!(bool, u8);
113119

114120
// SAFETY:
@@ -134,7 +140,8 @@ const _: () = unsafe { unsafe_impl!(char: Immutable, FromZeros, IntoBytes) };
134140
// `char`.
135141
const _: () = unsafe {
136142
unsafe_impl!(=> TryFromBytes for char; |c| {
137-
let c = c.transmute::<Unalign<u32>, invariant::Valid, _>();
143+
impl_size_eq!(ReadOnly<char>, Unalign<u32>);
144+
let c = c.transmute::<Unalign<u32>, invariant::Valid, BecauseImmutable>();
138145
let c = c.read_unaligned().into_inner();
139146
char::from_u32(c).is_some()
140147
});
@@ -167,7 +174,8 @@ const _: () = unsafe { unsafe_impl!(str: Immutable, FromZeros, IntoBytes, Unalig
167174
// Returns `Err` if the slice is not UTF-8.
168175
const _: () = unsafe {
169176
unsafe_impl!(=> TryFromBytes for str; |c| {
170-
let c = c.transmute::<[u8], invariant::Valid, _>();
177+
impl_size_eq!(ReadOnly<str>, [u8]);
178+
let c = c.transmute::<[u8], invariant::Valid, BecauseImmutable>();
171179
let c = c.unaligned_as_ref();
172180
core::str::from_utf8(c).is_ok()
173181
})
@@ -179,9 +187,10 @@ macro_rules! unsafe_impl_try_from_bytes_for_nonzero {
179187
($($nonzero:ident[$prim:ty]),*) => {
180188
$(
181189
unsafe_impl!(=> TryFromBytes for $nonzero; |n| {
182-
impl_size_eq!($nonzero, Unalign<$prim>);
190+
// impl_size_eq!($nonzero, Unalign<$prim>);
191+
impl_size_eq!(ReadOnly<$nonzero>, Unalign<$prim>);
183192

184-
let n = n.transmute::<Unalign<$prim>, invariant::Valid, _>();
193+
let n = n.transmute::<Unalign<$prim>, invariant::Valid, BecauseImmutable>();
185194
$nonzero::new(n.read_unaligned().into_inner()).is_some()
186195
});
187196
)*
@@ -390,6 +399,9 @@ mod atomics {
390399
macro_rules! impl_traits_for_atomics {
391400
($($atomics:ident [$primitives:ident]),* $(,)?) => {
392401
$(
402+
// impl_transitive_transmute_from!(T => ReadOnly<T> => T => Wrapping<T> => ReadOnly<Wrapping<T>>);
403+
// impl_size_eq!($atomics, ReadOnly<$atomics>);
404+
impl_transitive_transmute_from!(=> ReadOnly<$atomics> => $atomics => $primitives => ReadOnly<$primitives>);
393405
impl_known_layout!($atomics);
394406
impl_for_transmute_from!(=> TryFromBytes for $atomics [UnsafeCell<$primitives>]);
395407
impl_for_transmute_from!(=> FromZeros for $atomics [UnsafeCell<$primitives>]);
@@ -490,6 +502,7 @@ mod atomics {
490502

491503
impl_known_layout!(AtomicBool);
492504

505+
impl_transitive_transmute_from!(=> ReadOnly<AtomicBool> => AtomicBool => bool => ReadOnly<bool>);
493506
impl_for_transmute_from!(=> TryFromBytes for AtomicBool [UnsafeCell<bool>]);
494507
impl_for_transmute_from!(=> FromZeros for AtomicBool [UnsafeCell<bool>]);
495508
impl_for_transmute_from!(=> IntoBytes for AtomicBool [UnsafeCell<bool>]);
@@ -635,6 +648,7 @@ mod atomics {
635648

636649
// FIXME(#170): Implement `FromBytes` and `IntoBytes` once we implement
637650
// those traits for `*mut T`.
651+
impl_transitive_transmute_from!(T => ReadOnly<AtomicPtr<T>> => AtomicPtr<T> => *mut T => ReadOnly<*mut T>);
638652
impl_for_transmute_from!(T => TryFromBytes for AtomicPtr<T> [UnsafeCell<*mut T>]);
639653
impl_for_transmute_from!(T => FromZeros for AtomicPtr<T> [UnsafeCell<*mut T>]);
640654

@@ -682,6 +696,7 @@ const _: () = unsafe {
682696
assert_unaligned!(PhantomData<()>, PhantomData<u8>, PhantomData<u64>);
683697
};
684698

699+
impl_transitive_transmute_from!(T => ReadOnly<T> => T => Wrapping<T> => ReadOnly<Wrapping<T>>);
685700
impl_for_transmute_from!(T: TryFromBytes => TryFromBytes for Wrapping<T>[<T>]);
686701
impl_for_transmute_from!(T: FromZeros => FromZeros for Wrapping<T>[<T>]);
687702
impl_for_transmute_from!(T: FromBytes => FromBytes for Wrapping<T>[<T>]);
@@ -755,6 +770,7 @@ assert_unaligned!(CoreMaybeUninit<()>, CoreMaybeUninit<u8>);
755770
// [2] https://doc.rust-lang.org/1.85.0/std/mem/struct.ManuallyDrop.html#impl-Deref-for-ManuallyDrop%3CT%3E
756771
const _: () = unsafe { unsafe_impl!(T: ?Sized + Immutable => Immutable for ManuallyDrop<T>) };
757772

773+
impl_transitive_transmute_from!(T: ?Sized => ReadOnly<T> => T => ManuallyDrop<T> => ReadOnly<ManuallyDrop<T>>);
758774
impl_for_transmute_from!(T: ?Sized + TryFromBytes => TryFromBytes for ManuallyDrop<T>[<T>]);
759775
impl_for_transmute_from!(T: ?Sized + FromZeros => FromZeros for ManuallyDrop<T>[<T>]);
760776
impl_for_transmute_from!(T: ?Sized + FromBytes => FromBytes for ManuallyDrop<T>[<T>]);
@@ -769,6 +785,7 @@ impl_for_transmute_from!(T: ?Sized + IntoBytes => IntoBytes for ManuallyDrop<T>[
769785
const _: () = unsafe { unsafe_impl!(T: ?Sized + Unaligned => Unaligned for ManuallyDrop<T>) };
770786
assert_unaligned!(ManuallyDrop<()>, ManuallyDrop<u8>);
771787

788+
impl_transitive_transmute_from!(T: ?Sized => ReadOnly<T> => T => Cell<T> => ReadOnly<Cell<T>>);
772789
impl_for_transmute_from!(T: ?Sized + TryFromBytes => TryFromBytes for Cell<T>[UnsafeCell<T>]);
773790
impl_for_transmute_from!(T: ?Sized + FromZeros => FromZeros for Cell<T>[UnsafeCell<T>]);
774791
impl_for_transmute_from!(T: ?Sized + FromBytes => FromBytes for Cell<T>[UnsafeCell<T>]);
@@ -804,29 +821,16 @@ unsafe impl<T: TryFromBytes + ?Sized> TryFromBytes for UnsafeCell<T> {
804821
}
805822

806823
#[inline]
807-
fn is_bit_valid<A: invariant::Reference>(candidate: Maybe<'_, Self, A>) -> bool {
808-
// The only way to implement this function is using an exclusive-aliased
809-
// pointer. `UnsafeCell`s cannot be read via shared-aliased pointers
810-
// (other than by using `unsafe` code, which we can't use since we can't
811-
// guarantee how our users are accessing or modifying the `UnsafeCell`).
812-
//
813-
// `is_bit_valid` is documented as panicking or failing to monomorphize
814-
// if called with a shared-aliased pointer on a type containing an
815-
// `UnsafeCell`. In practice, it will always be a monorphization error.
816-
// Since `is_bit_valid` is `#[doc(hidden)]` and only called directly
817-
// from this crate, we only need to worry about our own code incorrectly
818-
// calling `UnsafeCell::is_bit_valid`. The post-monomorphization error
819-
// makes it easier to test that this is truly the case, and also means
820-
// that if we make a mistake, it will cause downstream code to fail to
821-
// compile, which will immediately surface the mistake and give us a
822-
// chance to fix it quickly.
823-
let c = candidate.into_exclusive_or_pme();
824-
825-
// SAFETY: Since `UnsafeCell<T>` and `T` have the same layout and bit
826-
// validity, `UnsafeCell<T>` is bit-valid exactly when its wrapped `T`
827-
// is. Thus, this is a sound implementation of
828-
// `UnsafeCell::is_bit_valid`.
829-
T::is_bit_valid(c.get_mut())
824+
fn is_bit_valid(candidate: Maybe<'_, Self>) -> bool {
825+
impl_transitive_transmute_from!(T: ?Sized => ReadOnly<UnsafeCell<T>> => UnsafeCell<T> => T);
826+
impl_transitive_transmute_from!(T: ?Sized => ReadOnly<UnsafeCell<T>> => T => ReadOnly<T>);
827+
// unsafe { impl_size_eq!(T: ?Sized => ReadOnly<UnsafeCell<T>>, ReadOnly<T>) };
828+
// unsafe impl<T: ?Sized> SizeEq<ReadOnly<UnsafeCell<T>>> for ReadOnly<T> {
829+
// fn cast_from_raw(t: pointer::PtrInner<'_, ReadOnly<UnsafeCell<T>>>) -> pointer::PtrInner<'_, Self> {
830+
// todo!()
831+
// }
832+
// }
833+
T::is_bit_valid(candidate.transmute::<_, _, BecauseImmutable>())
830834
}
831835
}
832836

@@ -854,11 +858,14 @@ unsafe impl<T: TryFromBytes + ?Sized> TryFromBytes for UnsafeCell<T> {
854858
const _: () = unsafe {
855859
unsafe_impl!(const N: usize, T: Immutable => Immutable for [T; N]);
856860
unsafe_impl!(const N: usize, T: TryFromBytes => TryFromBytes for [T; N]; |c| {
861+
unsafe { impl_size_eq!(T => ReadOnly<[T]>, [ReadOnly<T>]) };
862+
unsafe { impl_size_eq!(const N: usize, T => ReadOnly<[T; N]>, [ReadOnly<T>; N]) };
857863
// Note that this call may panic, but it would still be sound even if it
858864
// did. `is_bit_valid` does not promise that it will not panic (in fact,
859865
// it explicitly warns that it's a possibility), and we have not
860866
// violated any safety invariants that we must fix before returning.
861-
<[T] as TryFromBytes>::is_bit_valid(c.as_slice())
867+
let c: Ptr<'_, [ReadOnly<T>; N], _> = c.transmute::<_, _, BecauseImmutable>();
868+
<[T] as TryFromBytes>::is_bit_valid(c.as_slice().transmute::<_, _, BecauseImmutable>())
862869
});
863870
unsafe_impl!(const N: usize, T: FromZeros => FromZeros for [T; N]);
864871
unsafe_impl!(const N: usize, T: FromBytes => FromBytes for [T; N]);
@@ -887,6 +894,7 @@ const _: () = unsafe {
887894
// not panic (in fact, it explicitly warns that it's a possibility), and
888895
// we have not violated any safety invariants that we must fix before
889896
// returning.
897+
let c: Ptr<'_, [ReadOnly<T>], _> = c.transmute::<_, _, BecauseImmutable>();
890898
c.iter().all(<T as TryFromBytes>::is_bit_valid)
891899
});
892900
unsafe_impl!(T: FromZeros => FromZeros for [T]);
@@ -1096,12 +1104,12 @@ mod tests {
10961104
// types must implement `TryFromBytesTestable` directly (ie using
10971105
// `impl_try_from_bytes_testable!`).
10981106
trait TryFromBytesTestable {
1099-
fn with_passing_test_cases<F: Fn(Box<Self>)>(f: F);
1107+
fn with_passing_test_cases<F: Fn(Box<ReadOnly<Self>>)>(f: F);
11001108
fn with_failing_test_cases<F: Fn(&mut [u8])>(f: F);
11011109
}
11021110

11031111
impl<T: FromBytes> TryFromBytesTestable for T {
1104-
fn with_passing_test_cases<F: Fn(Box<Self>)>(f: F) {
1112+
fn with_passing_test_cases<F: Fn(Box<ReadOnly<Self>>)>(f: F) {
11051113
// Test with a zeroed value.
11061114
f(Self::new_box_zeroed().unwrap());
11071115

@@ -1124,9 +1132,9 @@ mod tests {
11241132
($($tys:ty),*) => {
11251133
$(
11261134
impl TryFromBytesTestable for Option<$tys> {
1127-
fn with_passing_test_cases<F: Fn(Box<Self>)>(f: F) {
1135+
fn with_passing_test_cases<F: Fn(Box<ReadOnly<Self>>)>(f: F) {
11281136
// Test with a zeroed value.
1129-
f(Box::new(None));
1137+
f(Box::new(ReadOnly::new(None)));
11301138
}
11311139

11321140
fn with_failing_test_cases<F: Fn(&mut [u8])>(f: F) {
@@ -1164,7 +1172,7 @@ mod tests {
11641172
// Implements only the methods; caller must invoke this from inside
11651173
// an impl block.
11661174
(@methods @success $($success_case:expr),* $(, @failure $($failure_case:expr),*)?) => {
1167-
fn with_passing_test_cases<F: Fn(Box<Self>)>(_f: F) {
1175+
fn with_passing_test_cases<F: Fn(Box<ReadOnly<Self>>)>(_f: F) {
11681176
$(
11691177
_f(Box::<Self>::from($success_case));
11701178
)*
@@ -1266,17 +1274,15 @@ mod tests {
12661274

12671275
pub(super) trait TestIsBitValidShared<T: ?Sized> {
12681276
#[allow(clippy::needless_lifetimes)]
1269-
fn test_is_bit_valid_shared<'ptr, A: invariant::Reference>(
1270-
&self,
1271-
candidate: Maybe<'ptr, T, A>,
1272-
) -> Option<bool>;
1277+
fn test_is_bit_valid_shared<'ptr>(&self, candidate: Maybe<'ptr, T>)
1278+
-> Option<bool>;
12731279
}
12741280

12751281
impl<T: TryFromBytes + Immutable + ?Sized> TestIsBitValidShared<T> for AutorefWrapper<T> {
12761282
#[allow(clippy::needless_lifetimes)]
1277-
fn test_is_bit_valid_shared<'ptr, A: invariant::Reference>(
1283+
fn test_is_bit_valid_shared<'ptr>(
12781284
&self,
1279-
candidate: Maybe<'ptr, T, A>,
1285+
candidate: Maybe<'ptr, T>,
12801286
) -> Option<bool> {
12811287
Some(T::is_bit_valid(candidate))
12821288
}
@@ -1330,12 +1336,12 @@ mod tests {
13301336

13311337
pub(super) trait TestAsBytes<T: ?Sized> {
13321338
#[allow(clippy::needless_lifetimes)]
1333-
fn test_as_bytes<'slf, 't>(&'slf self, t: &'t T) -> Option<&'t [u8]>;
1339+
fn test_as_bytes<'slf, 't>(&'slf self, t: &'t ReadOnly<T>) -> Option<&'t [u8]>;
13341340
}
13351341

13361342
impl<T: IntoBytes + Immutable + ?Sized> TestAsBytes<T> for AutorefWrapper<T> {
13371343
#[allow(clippy::needless_lifetimes)]
1338-
fn test_as_bytes<'slf, 't>(&'slf self, t: &'t T) -> Option<&'t [u8]> {
1344+
fn test_as_bytes<'slf, 't>(&'slf self, t: &'t ReadOnly<T>) -> Option<&'t [u8]> {
13391345
Some(t.as_bytes())
13401346
}
13411347
}
@@ -1382,9 +1388,9 @@ mod tests {
13821388
#[allow(unused, non_local_definitions)]
13831389
impl AutorefWrapper<$ty> {
13841390
#[allow(clippy::needless_lifetimes)]
1385-
fn test_is_bit_valid_shared<'ptr, A: invariant::Reference>(
1391+
fn test_is_bit_valid_shared<'ptr>(
13861392
&mut self,
1387-
candidate: Maybe<'ptr, $ty, A>,
1393+
candidate: Maybe<'ptr, $ty>,
13881394
) -> Option<bool> {
13891395
assert_on_allowlist!(
13901396
test_is_bit_valid_shared($ty):
@@ -1442,7 +1448,7 @@ mod tests {
14421448
None
14431449
}
14441450

1445-
fn test_as_bytes(&mut self, _t: &$ty) -> Option<&[u8]> {
1451+
fn test_as_bytes(&mut self, _t: &ReadOnly<$ty>) -> Option<&[u8]> {
14461452
assert_on_allowlist!(
14471453
test_as_bytes($ty):
14481454
Option<&'static UnsafeCell<NotZerocopy>>,
@@ -1491,6 +1497,7 @@ mod tests {
14911497
// necessarily `IntoBytes`, but that's the corner we've
14921498
// backed ourselves into by using `Ptr::from_ref`.
14931499
let c = unsafe { c.assume_initialized() };
1500+
let c = unsafe { c.assume_aliasing::<Shared>() };
14941501
let res = w.test_is_bit_valid_shared(c);
14951502
if let Some(res) = res {
14961503
assert!(res, "{}::is_bit_valid({:?}) (shared `Ptr`): got false, expected true", stringify!($ty), val);
@@ -1502,6 +1509,7 @@ mod tests {
15021509
// necessarily `IntoBytes`, but that's the corner we've
15031510
// backed ourselves into by using `Ptr::from_ref`.
15041511
let c = unsafe { c.assume_initialized() };
1512+
let c = unsafe { c.assume_aliasing() };
15051513
let res = <$ty as TryFromBytes>::is_bit_valid(c);
15061514
assert!(res, "{}::is_bit_valid({:?}) (exclusive `Ptr`): got false, expected true", stringify!($ty), val);
15071515

src/lib.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ use core::{
386386
#[cfg(feature = "std")]
387387
use std::io;
388388

389-
use crate::pointer::invariant::{self, BecauseExclusive};
389+
use crate::pointer::invariant::{self, BecauseExclusive, Initialized};
390390
pub use crate::{
391391
byte_slice::*,
392392
byteorder::*,
@@ -1520,7 +1520,7 @@ pub unsafe trait TryFromBytes {
15201520
/// [`UnsafeCell`]: core::cell::UnsafeCell
15211521
/// [`Shared`]: invariant::Shared
15221522
#[doc(hidden)]
1523-
fn is_bit_valid<A: invariant::Reference>(candidate: Maybe<'_, Self, A>) -> bool;
1523+
fn is_bit_valid(candidate: Maybe<'_, Self>) -> bool;
15241524

15251525
/// Attempts to interpret the given `source` as a `&Self`.
15261526
///
@@ -2928,7 +2928,12 @@ unsafe fn try_read_from<S, T: TryFromBytes>(
29282928
// via `c_ptr` so long as it is live, so we don't need to worry about the
29292929
// fact that `c_ptr` may have more restricted validity than `candidate`.
29302930
let c_ptr = unsafe { c_ptr.assume_validity::<invariant::Initialized>() };
2931-
let c_ptr = c_ptr.transmute();
2931+
let c_ptr = c_ptr.transmute::<T, _, _>();
2932+
// unsafe { impl_size_eq!(T => T, Wrapping<T>) };
2933+
impl_transitive_transmute_from!(T => T => Wrapping<T> => ReadOnly<Wrapping<T>>);
2934+
let c_ptr: Ptr<'_, _, (invariant::Exclusive, invariant::Aligned, Initialized)> = todo!();
2935+
// let c_ptr = c_ptr.transmute::<ReadOnly<Wrapping<T>>, Initialized, BecauseExclusive>();
2936+
// let c_ptr = c_ptr.transmute();
29322937

29332938
// Since we don't have `T: KnownLayout`, we hack around that by using
29342939
// `Wrapping<T>`, which implements `KnownLayout` even if `T` doesn't.
@@ -2941,7 +2946,8 @@ unsafe fn try_read_from<S, T: TryFromBytes>(
29412946
// `try_into_valid` (and thus `is_bit_valid`) with a shared pointer when
29422947
// `Self: !Immutable`. Since `Self: Immutable`, this panic condition will
29432948
// not happen.
2944-
if !Wrapping::<T>::is_bit_valid(c_ptr.forget_aligned()) {
2949+
let shared = unsafe { c_ptr.assume_aliasing::<invariant::Shared>() };
2950+
if !Wrapping::<T>::is_bit_valid(shared.forget_aligned()) {
29452951
return Err(ValidityError::new(source).into());
29462952
}
29472953

src/macros.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -895,10 +895,7 @@ macro_rules! cryptocorrosion_derive_traits {
895895
$($field_ty: $crate::FromBytes,)*
896896
)?
897897
{
898-
fn is_bit_valid<A>(_c: $crate::Maybe<'_, Self, A>) -> bool
899-
where
900-
A: $crate::pointer::invariant::Reference
901-
{
898+
fn is_bit_valid(_c: $crate::Maybe<'_, Self>) -> bool {
902899
// SAFETY: This macro only accepts `#[repr(C)]` and
903900
// `#[repr(transparent)]` structs, and this `impl` block
904901
// requires all field types to be `FromBytes`. Thus, all
@@ -1038,10 +1035,7 @@ macro_rules! cryptocorrosion_derive_traits {
10381035
$field_ty: $crate::FromBytes,
10391036
)*
10401037
{
1041-
fn is_bit_valid<A>(_c: $crate::Maybe<'_, Self, A>) -> bool
1042-
where
1043-
A: $crate::pointer::invariant::Reference
1044-
{
1038+
fn is_bit_valid(_c: $crate::Maybe<'_, Self>) -> bool {
10451039
// SAFETY: This macro only accepts `#[repr(C)]` unions, and this
10461040
// `impl` block requires all field types to be `FromBytes`.
10471041
// Thus, all initialized byte sequences constitutes valid

src/pointer/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub use {
2727
///
2828
/// [`TryFromBytes::is_bit_valid`]: crate::TryFromBytes::is_bit_valid
2929
pub type Maybe<'a, T, Aliasing = invariant::Shared, Alignment = invariant::Unaligned> =
30-
Ptr<'a, T, (Aliasing, Alignment, invariant::Initialized)>;
30+
Ptr<'a, crate::wrappers::ReadOnly<T>, (Aliasing, Alignment, invariant::Initialized)>;
3131

3232
/// Checks if the referent is zeroed.
3333
pub(crate) fn is_zeroed<T, I>(ptr: Ptr<'_, T, I>) -> bool

src/pointer/ptr.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ mod _conversions {
532532
/// State transitions between invariants.
533533
mod _transitions {
534534
use super::*;
535-
use crate::pointer::transmute::TryTransmuteFromPtr;
535+
use crate::{pointer::transmute::TryTransmuteFromPtr, ReadOnly};
536536

537537
impl<'a, T, I> Ptr<'a, T, I>
538538
where
@@ -807,10 +807,12 @@ mod _transitions {
807807
I::Aliasing: Reference,
808808
I: Invariants<Validity = Initialized>,
809809
{
810+
let ro: Ptr<'_, ReadOnly<T>, _> = self.reborrow().transmute();
811+
let shared = unsafe { ro.assume_aliasing::<Shared>() };
810812
// This call may panic. If that happens, it doesn't cause any soundness
811813
// issues, as we have not generated any invalid state which we need to
812814
// fix before returning.
813-
if T::is_bit_valid(self.reborrow().forget_aligned()) {
815+
if T::is_bit_valid(shared) {
814816
// SAFETY: If `T::is_bit_valid`, code may assume that `self`
815817
// contains a bit-valid instance of `T`. By `T:
816818
// TryTransmuteFromPtr<T, I::Aliasing, I::Validity, Valid>`, so

0 commit comments

Comments
 (0)