Skip to content

Commit 7bc17a9

Browse files
committed
[WIP] Introduce compound Ptr validity
..and implement projection for compound-valid tuples. gherrit-pr-id: G06edd27f8b77b5ad480ca94749098bb4b0808342
1 parent 4070001 commit 7bc17a9

File tree

3 files changed

+101
-55
lines changed

3 files changed

+101
-55
lines changed

src/impls.rs

Lines changed: 85 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -994,19 +994,19 @@ mod tuples {
994994
///
995995
/// # Safety
996996
///
997-
/// `impl_tuple!` should be provided name-number pairs, where each number is
998-
/// the ordinal of the preceding type name.
997+
/// `impl_tuple!` should be provided name-validity-number triplets, where
998+
/// each number is the ordinal of the triplet.
999999
macro_rules! impl_tuple {
10001000
// Entry point.
1001-
($($T:ident $I:tt),+ $(,)?) => {
1001+
($($T:ident $V:ident $I:tt),+ $(,)?) => {
10021002
crate::util::macros::__unsafe();
1003-
impl_tuple!(@all [] [$($T $I)+]);
1003+
impl_tuple!(@all [] [$($T $V $I)+]);
10041004
};
10051005

10061006
// Build up the set of tuple types (i.e., `(A,)`, `(A, B)`, `(A, B, C)`,
10071007
// etc.) Trait implementations that do not depend on field index may be
10081008
// added to this branch.
1009-
(@all [$($head_T:ident $head_I:tt)*] [$next_T:ident $next_I:tt $($tail:tt)*]) => {
1009+
(@all [$($head_T:ident $head_V:ident $head_I:tt)*] [$next_T:ident $next_V:ident $next_I:tt $($tail:tt)*]) => {
10101010
// SAFETY: If all fields of the tuple `Self` are `Immutable`, so too is `Self`.
10111011
unsafe_impl!($($head_T: Immutable,)* $next_T: Immutable => Immutable for ($($head_T,)* $next_T,));
10121012

@@ -1023,6 +1023,19 @@ mod tuples {
10231023
// SAFETY: If all fields in `Self` are `FromBytes`, so too is `Self`.
10241024
unsafe_impl!($($head_T: FromBytes,)* $next_T: FromBytes => FromBytes for ($($head_T,)* $next_T,));
10251025

1026+
// SAFETY: TODO
1027+
unsafe impl<$($head_T,)* $next_T> crate::invariant::Validity for ($($head_T,)* $next_T,)
1028+
where
1029+
$($head_T: crate::invariant::Validity,)*
1030+
$next_T: crate::invariant::Validity,
1031+
{
1032+
const KIND: crate::invariant::ValidityKind = crate::invariant::ValidityKind::Compound(&[
1033+
$($head_T::KIND,)*
1034+
$next_T::KIND,
1035+
]);
1036+
}
1037+
impl<$($head_T,)* $next_T> crate::invariant::sealed::Sealed for ($($head_T,)* $next_T,) {}
1038+
10261039
// SAFETY: See safety comment on `ProjectToTag`.
10271040
unsafe impl<$($head_T,)* $next_T> crate::HasTag for ($($head_T,)* $next_T,) {
10281041
#[inline]
@@ -1048,24 +1061,24 @@ mod tuples {
10481061

10491062
// Generate impls that depend on tuple index.
10501063
impl_tuple!(@variants
1051-
[$($head_T $head_I)* $next_T $next_I]
1064+
[$($head_T $head_V $head_I)* $next_T $next_V $next_I]
10521065
[]
1053-
[$($head_T $head_I)* $next_T $next_I]
1066+
[$($head_T $head_V $head_I)* $next_T $next_V $next_I]
10541067
);
10551068

10561069
// Recurse to next tuple size
1057-
impl_tuple!(@all [$($head_T $head_I)* $next_T $next_I] [$($tail)*]);
1070+
impl_tuple!(@all [$($head_T $head_V $head_I)* $next_T $next_V $next_I] [$($tail)*]);
10581071
};
1059-
(@all [$($head_T:ident $head_I:tt)*] []) => {};
1072+
(@all [$($head_T:ident $head_V:ident $head_I:tt)*] []) => {};
10601073

10611074
// Emit trait implementations that depend on field index.
10621075
(@variants
1063-
// The full tuple definition in type–index pairs.
1064-
[$($AllT:ident $AllI:tt)+]
1076+
// The full tuple definition in type–ident-index triplets.
1077+
[$($AllT:ident $AllV:ident $AllI:tt)+]
10651078
// Types before the current index.
1066-
[$($BeforeT:ident)*]
1079+
[$($BeforeT:ident $BeforeV:ident)*]
10671080
// The types and indices at and after the current index.
1068-
[$CurrT:ident $CurrI:tt $($AfterT:ident $AfterI:tt)*]
1081+
[$CurrT:ident $CurrV:ident $CurrI:tt $($AfterT:ident $AfterV:ident $AfterI:tt)*]
10691082
) => {
10701083
// SAFETY:
10711084
// - `Self` is a struct (albeit anonymous), so `VARIANT_ID` is
@@ -1178,47 +1191,75 @@ mod tuples {
11781191
type Error = core::convert::Infallible;
11791192
}
11801193

1194+
// SAFETY: See comments on items.
1195+
unsafe impl<Aliasing, Alignment, $($AllT,)+ $($AllV),+> crate::ProjectField<
1196+
(),
1197+
(Aliasing, Alignment, ($($AllV,)+)),
1198+
{ crate::STRUCT_VARIANT_ID },
1199+
{ crate::ident_id!($CurrI)}
1200+
> for ($($AllT,)+)
1201+
where
1202+
Aliasing: crate::invariant::Aliasing,
1203+
Alignment: crate::invariant::Alignment,
1204+
$($AllV: crate::invariant::Validity,)*
1205+
{
1206+
#[inline]
1207+
fn only_derive_is_allowed_to_implement_this_trait()
1208+
where
1209+
Self: Sized
1210+
{}
1211+
1212+
// SAFETY: Tuples are product types whose fields are
1213+
// well-aligned, so projection preserves the alignment invariant
1214+
// of the outer pointer. The outer pointer's validity is a tuple
1215+
// of the validity of its fields, so the validity of the
1216+
// projected field is the projected of that validity tuple.
1217+
type Invariants = (Aliasing, Alignment, $CurrV);
1218+
1219+
// SAFETY: Tuples are product types and so projection is infallible;
1220+
type Error = core::convert::Infallible;
1221+
}
1222+
11811223
// Recurse to the next index.
1182-
impl_tuple!(@variants [$($AllT $AllI)+] [$($BeforeT)* $CurrT] [$($AfterT $AfterI)*]);
1224+
impl_tuple!(@variants [$($AllT $AllV $AllI)+] [$($BeforeT $BeforeV)* $CurrT $CurrV] [$($AfterT $AfterV $AfterI)*]);
11831225
};
1184-
(@variants [$($AllT:ident $AllI:tt)+] [$($BeforeT:ident)*] []) => {};
1226+
(@variants [$($AllT:ident $AllV:ident $AllI:tt)+] [$($BeforeT:ident $BeforeV:ident)*] []) => {};
11851227
}
11861228

1187-
// SAFETY: `impl_tuple` is provided name-number pairs, where number is the
1188-
// ordinal of the name.
1229+
// SAFETY: `impl_tuple` is provided name-validity-number triplets, where
1230+
// number is the ordinal of the triplet.
11891231
#[allow(clippy::multiple_unsafe_ops_per_block)]
11901232
const _: () = unsafe {
11911233
impl_tuple! {
1192-
A 0,
1193-
B 1,
1194-
C 2,
1195-
D 3,
1196-
E 4,
1197-
F 5,
1198-
G 6,
1199-
H 7,
1200-
I 8,
1201-
J 9,
1202-
K 10,
1203-
L 11,
1204-
M 12,
1205-
N 13,
1206-
O 14,
1207-
P 15,
1208-
Q 16,
1209-
R 17,
1210-
S 18,
1211-
T 19,
1212-
U 20,
1213-
V 21,
1214-
W 22,
1215-
X 23,
1216-
Y 24,
1217-
Z 25,
1234+
A VA 0,
1235+
B VB 1,
1236+
C VC 2,
1237+
D VD 3,
1238+
E VE 4,
1239+
F VF 5,
1240+
G VG 6,
1241+
H VH 7,
1242+
I VI 8,
1243+
J VJ 9,
1244+
K VK 10,
1245+
L VL 11,
1246+
M VM 12,
1247+
N VN 13,
1248+
O VO 14,
1249+
P VP 15,
1250+
Q VQ 16,
1251+
R VR 17,
1252+
S VS 18,
1253+
T VT 19,
1254+
U VU 20,
1255+
V VV 21,
1256+
W VW 22,
1257+
X VX 23,
1258+
Y VY 24,
1259+
Z VZ 25,
12181260
};
12191261
};
12201262
}
1221-
12221263
// SIMD support
12231264
//
12241265
// Per the Unsafe Code Guidelines Reference [1]:

src/lib.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,14 +1268,18 @@ where
12681268
_enum_variant => {
12691269
use crate::invariant::{Validity, ValidityKind};
12701270
match I::Validity::KIND {
1271-
// The `Uninit` and `Initialized` validity
1272-
// invariants do not depend on the enum's tag. In
1273-
// particular, we don't actually care about what
1274-
// variant is present – we can treat *any* range of
1275-
// uninitialized or initialized memory as containing
1276-
// an uninitialized or initialized instance of *any*
1277-
// type – the type itself is irrelevant.
1278-
ValidityKind::Uninit | ValidityKind::Initialized => true,
1271+
// The `Uninit`, `Initialized` and `Compound`
1272+
// validity invariants do not depend on the enum's
1273+
// tag. In particular, we don't actually care about
1274+
// what variant is present – we can treat *any*
1275+
// range of uninitialized or initialized memory as
1276+
// containing an uninitialized or initialized
1277+
// instance of *any* type – the type itself is
1278+
// irrelevant.
1279+
// TODO: What about compound validity?
1280+
ValidityKind::Uninit
1281+
| ValidityKind::Initialized
1282+
| ValidityKind::Compound(..) => true,
12791283
// The projectability of an enum field from an
12801284
// `AsInitialized` or `Valid` state is a dynamic
12811285
// property of its tag.

src/pointer/invariant.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ pub trait Alignment: Sealed {
6464
/// other property of `T`. As a consequence, given `V: Validity`, `T`, and `U`
6565
/// where `T` and `U` have the same bit validity, `S(V, T) = S(V, U)`.
6666
///
67+
/// TODO: Document compound validity.
68+
///
6769
/// It is guaranteed that the referent of any `ptr: Ptr<T, V>` is a member of
6870
/// `S(T, V)`. Unsafe code must ensure that this guarantee will be upheld for
6971
/// any existing `Ptr`s or any `Ptr`s that that code creates.
@@ -100,6 +102,7 @@ pub enum ValidityKind {
100102
AsInitialized,
101103
Initialized,
102104
Valid,
105+
Compound(&'static [ValidityKind]),
103106
}
104107

105108
/// An [`Aliasing`] invariant which is either [`Shared`] or [`Exclusive`].
@@ -275,7 +278,7 @@ pub enum BecauseExclusive {}
275278
pub enum BecauseImmutable {}
276279

277280
use sealed::Sealed;
278-
mod sealed {
281+
pub(crate) mod sealed {
279282
use super::*;
280283

281284
pub trait Sealed {}
@@ -291,8 +294,6 @@ mod sealed {
291294
impl Sealed for Initialized {}
292295
impl Sealed for Valid {}
293296

294-
impl<A: Sealed, AA: Sealed, V: Sealed> Sealed for (A, AA, V) {}
295-
296297
impl Sealed for BecauseImmutable {}
297298
impl Sealed for BecauseExclusive {}
298299
}

0 commit comments

Comments
 (0)