Skip to content

Commit 802915a

Browse files
committed
[project] Support projecting enum tags
gherrit-pr-id: G06bb22c59364654d5c0b44cdcb9b70ad58fe8092
1 parent 1f5eea2 commit 802915a

10 files changed

Lines changed: 223 additions & 10 deletions

File tree

src/impls.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,10 @@ const _: () = {
781781
{
782782
type Type = T;
783783

784+
type Tag = ();
785+
786+
type ProjectToTag = crate::pointer::cast::CastToUnit;
787+
784788
#[inline]
785789
fn only_derive_is_allowed_to_implement_this_trait()
786790
where
@@ -1058,6 +1062,10 @@ mod tuples {
10581062

10591063
type Type = $CurrT;
10601064

1065+
type Tag = ();
1066+
1067+
type ProjectToTag = crate::pointer::cast::CastToUnit;
1068+
10611069
#[inline(always)]
10621070
fn project(slf: crate::PtrInner<'_, Self>) -> *mut Self::Type {
10631071
let slf = slf.as_non_null().as_ptr();

src/lib.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,6 +1105,14 @@ pub const STRUCT_VARIANT_ID: i128 = -1;
11051105
#[doc(hidden)]
11061106
pub const UNION_VARIANT_ID: i128 = -2;
11071107

1108+
#[doc(hidden)]
1109+
pub const ENUM_TAG_VARIANT_ID: i128 = -3;
1110+
#[doc(hidden)]
1111+
pub const ENUM_TAG_FIELD_ID: i128 = 0;
1112+
#[doc(hidden)]
1113+
#[allow(missing_copy_implementations, missing_debug_implementations)]
1114+
pub enum Tag {}
1115+
11081116
/// Projects a given field from `Self`.
11091117
///
11101118
/// All implementations of `HasField` for a particular field `f` in `Self`
@@ -1139,6 +1147,16 @@ pub unsafe trait HasField<Field, const VARIANT_ID: i128, const FIELD_ID: i128> {
11391147
/// The type of the field.
11401148
type Type: ?Sized;
11411149

1150+
/// The type's enum tag, or `()` for non-enum types.
1151+
type Tag: Immutable;
1152+
1153+
/// A pointer projection from `Self` to its tag.
1154+
///
1155+
/// # Safety
1156+
///
1157+
/// TODO
1158+
type ProjectToTag: pointer::cast::Project<Self, Self::Tag>;
1159+
11421160
/// Projects from `slf` to the field.
11431161
///
11441162
/// Users should generally not call `project` directly, and instead should
@@ -1185,6 +1203,16 @@ where
11851203
/// otherwise [`core::convert::Infallible`].
11861204
type Error;
11871205

1206+
#[must_use]
1207+
#[inline(always)]
1208+
fn project_tag<'a>(ptr: Ptr<'a, Self, I>) -> Ptr<'a, Self::Tag, I> {
1209+
// SAFETY: TODO
1210+
let tag = unsafe { ptr.project_transmute_unchecked::<_, _, Self::ProjectToTag>() };
1211+
// SAFETY: TODO
1212+
let tag = unsafe { tag.assume_alignment() };
1213+
tag.unify_invariants()
1214+
}
1215+
11881216
/// Is the given field projectable from `ptr`?
11891217
///
11901218
/// If a field with [`Self::Invariants`] is projectable from the referent,
@@ -1194,7 +1222,7 @@ where
11941222
/// This method must be overriden if the field's projectability depends on
11951223
/// the value of the bytes in `ptr`.
11961224
#[inline(always)]
1197-
fn is_projectable<'a>(ptr: Ptr<'a, Self, I>) -> Result<Ptr<'a, Self, I>, Self::Error> {
1225+
fn is_projectable<'a>(_ptr: Ptr<'a, Self::Tag, I>) -> Result<(), Self::Error> {
11981226
trait IsInfallible {
11991227
const IS_INFALLIBLE: bool;
12001228
}
@@ -1248,7 +1276,7 @@ where
12481276
<Projection<Self, Field, I, VARIANT_ID, FIELD_ID> as IsInfallible>::IS_INFALLIBLE
12491277
);
12501278

1251-
Ok(ptr)
1279+
Ok(())
12521280
}
12531281
}
12541282

src/pointer/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,4 +347,20 @@ pub mod cast {
347347

348348
// SAFETY: The `Project::project` impl preserves the set of referent bytes.
349349
unsafe impl<T: ?Sized + KnownLayout> CastExact<T, [u8]> for AsBytesCast {}
350+
351+
/// A cast from any type to `()`.
352+
#[allow(missing_copy_implementations, missing_debug_implementations)]
353+
pub struct CastToUnit;
354+
355+
// SAFETY: The `project` implementation projects to a subset of its
356+
// argument's referent using provenance-preserving operations.
357+
unsafe impl<T: ?Sized> Project<T, ()> for CastToUnit {
358+
#[inline(always)]
359+
fn project(src: PtrInner<'_, T>) -> *mut () {
360+
src.as_ptr().cast::<()>()
361+
}
362+
}
363+
364+
// SAFETY: The `project` implementation preserves referent address.
365+
unsafe impl<T: ?Sized> Cast<T, ()> for CastToUnit {}
350366
}

src/pointer/ptr.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -886,15 +886,16 @@ mod _casts {
886886

887887
#[inline(always)]
888888
pub fn project<F, const VARIANT_ID: i128, const FIELD_ID: i128>(
889-
self,
889+
mut self,
890890
) -> Result<Ptr<'a, T::Type, T::Invariants>, T::Error>
891891
where
892892
T: ProjectField<F, I, VARIANT_ID, FIELD_ID>,
893+
I::Aliasing: Reference,
893894
{
894895
use crate::pointer::cast::Projection;
895-
match T::is_projectable(self) {
896-
Ok(ptr) => {
897-
let inner = ptr.as_inner();
896+
match T::is_projectable(T::project_tag(self.reborrow())) {
897+
Ok(()) => {
898+
let inner = self.as_inner();
898899
let projected = inner.project::<_, Projection<F, VARIANT_ID, FIELD_ID>>();
899900
// SAFETY: By `T: ProjectField<F, I, VARIANT_ID, FIELD_ID>`,
900901
// for `self: Ptr<'_, T, I>` such that `T::is_projectable`

zerocopy-derive/src/derive/try_from_bytes.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@ pub(crate) fn derive_is_bit_valid(
247247
.inner_extras(quote! {
248248
type Type = #ty;
249249

250+
type Tag = ___ZerocopyTag;
251+
252+
type ProjectToTag = #zerocopy_crate::pointer::cast::CastSized;
253+
250254
#[inline(always)]
251255
fn project(slf: #zerocopy_crate::pointer::PtrInner<'_, Self>) -> *mut <Self as #has_field_path>::Type {
252256
use #zerocopy_crate::pointer::cast::{CastSized, Projection};
@@ -483,6 +487,10 @@ fn derive_has_field_struct_union(ctx: &Ctx, data: &dyn DataExt) -> TokenStream {
483487
.inner_extras(quote! {
484488
type Type = #ty;
485489

490+
type Tag = ();
491+
492+
type ProjectToTag = #zerocopy_crate::pointer::cast::CastToUnit;
493+
486494
#[inline(always)]
487495
fn project(slf: #zerocopy_crate::pointer::PtrInner<'_, Self>) -> *mut <Self as #has_field_path>::Type {
488496
let slf = slf.as_ptr();

zerocopy-derive/src/output_tests/expected/from_bytes_union.expected.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ const _: () = {
6767
> for Foo {
6868
fn only_derive_is_allowed_to_implement_this_trait() {}
6969
type Type = u8;
70+
type Tag = ();
71+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
7072
#[inline(always)]
7173
fn project(
7274
slf: ::zerocopy::pointer::PtrInner<'_, Self>,

zerocopy-derive/src/output_tests/expected/try_from_bytes_enum_1.expected.rs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const _: () = {
3333
{
3434
#[repr(u8)]
3535
#[allow(dead_code)]
36-
enum ___ZerocopyTag {
36+
pub enum ___ZerocopyTag {
3737
UnitLike,
3838
StructLike,
3939
TupleLike,
@@ -283,6 +283,8 @@ const _: () = {
283283
type Type = ::zerocopy::util::macro_util::core_reexport::mem::MaybeUninit<
284284
___ZerocopyInnerTag,
285285
>;
286+
type Tag = ();
287+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
286288
#[inline(always)]
287289
fn project(
288290
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -366,6 +368,8 @@ const _: () = {
366368
{
367369
fn only_derive_is_allowed_to_implement_this_trait() {}
368370
type Type = u8;
371+
type Tag = ();
372+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
369373
#[inline(always)]
370374
fn project(
371375
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -449,6 +453,8 @@ const _: () = {
449453
{
450454
fn only_derive_is_allowed_to_implement_this_trait() {}
451455
type Type = X;
456+
type Tag = ();
457+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
452458
#[inline(always)]
453459
fn project(
454460
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -532,6 +538,8 @@ const _: () = {
532538
{
533539
fn only_derive_is_allowed_to_implement_this_trait() {}
534540
type Type = X::Target;
541+
type Tag = ();
542+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
535543
#[inline(always)]
536544
fn project(
537545
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -615,6 +623,8 @@ const _: () = {
615623
{
616624
fn only_derive_is_allowed_to_implement_this_trait() {}
617625
type Type = Y::Target;
626+
type Tag = ();
627+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
618628
#[inline(always)]
619629
fn project(
620630
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -698,6 +708,8 @@ const _: () = {
698708
{
699709
fn only_derive_is_allowed_to_implement_this_trait() {}
700710
type Type = [(X, Y); N];
711+
type Tag = ();
712+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
701713
#[inline(always)]
702714
fn project(
703715
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -783,6 +795,8 @@ const _: () = {
783795
type Type = ::zerocopy::util::macro_util::core_reexport::marker::PhantomData<
784796
ComplexWithGenerics<'a, N, X, Y>,
785797
>;
798+
type Tag = ();
799+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
786800
#[inline(always)]
787801
fn project(
788802
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -1030,6 +1044,8 @@ const _: () = {
10301044
type Type = ::zerocopy::util::macro_util::core_reexport::mem::MaybeUninit<
10311045
___ZerocopyInnerTag,
10321046
>;
1047+
type Tag = ();
1048+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
10331049
#[inline(always)]
10341050
fn project(
10351051
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -1113,6 +1129,8 @@ const _: () = {
11131129
{
11141130
fn only_derive_is_allowed_to_implement_this_trait() {}
11151131
type Type = bool;
1132+
type Tag = ();
1133+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
11161134
#[inline(always)]
11171135
fn project(
11181136
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -1196,6 +1214,8 @@ const _: () = {
11961214
{
11971215
fn only_derive_is_allowed_to_implement_this_trait() {}
11981216
type Type = Y;
1217+
type Tag = ();
1218+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
11991219
#[inline(always)]
12001220
fn project(
12011221
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -1279,6 +1299,8 @@ const _: () = {
12791299
{
12801300
fn only_derive_is_allowed_to_implement_this_trait() {}
12811301
type Type = PhantomData<&'a [(X, Y); N]>;
1302+
type Tag = ();
1303+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
12821304
#[inline(always)]
12831305
fn project(
12841306
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -1364,6 +1386,8 @@ const _: () = {
13641386
type Type = ::zerocopy::util::macro_util::core_reexport::marker::PhantomData<
13651387
ComplexWithGenerics<'a, N, X, Y>,
13661388
>;
1389+
type Tag = ();
1390+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
13671391
#[inline(always)]
13681392
fn project(
13691393
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -1474,6 +1498,8 @@ const _: () = {
14741498
type Type = ::zerocopy::util::macro_util::core_reexport::mem::ManuallyDrop<
14751499
___ZerocopyVariantStruct_StructLike<'a, N, X, Y>,
14761500
>;
1501+
type Tag = ();
1502+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
14771503
#[inline(always)]
14781504
fn project(
14791505
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -1534,6 +1560,8 @@ const _: () = {
15341560
type Type = ::zerocopy::util::macro_util::core_reexport::mem::ManuallyDrop<
15351561
___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>,
15361562
>;
1563+
type Tag = ();
1564+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
15371565
#[inline(always)]
15381566
fn project(
15391567
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -1592,6 +1620,8 @@ const _: () = {
15921620
> for ___ZerocopyVariants<'a, { N }, X, Y> {
15931621
fn only_derive_is_allowed_to_implement_this_trait() {}
15941622
type Type = ();
1623+
type Tag = ();
1624+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
15951625
#[inline(always)]
15961626
fn project(
15971627
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -1679,6 +1709,8 @@ const _: () = {
16791709
> for ___ZerocopyRawEnum<'a, { N }, X, Y> {
16801710
fn only_derive_is_allowed_to_implement_this_trait() {}
16811711
type Type = ___ZerocopyOuterTag;
1712+
type Tag = ();
1713+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
16821714
#[inline(always)]
16831715
fn project(
16841716
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -1756,6 +1788,8 @@ const _: () = {
17561788
> for ___ZerocopyRawEnum<'a, { N }, X, Y> {
17571789
fn only_derive_is_allowed_to_implement_this_trait() {}
17581790
type Type = ___ZerocopyVariants<'a, N, X, Y>;
1791+
type Tag = ();
1792+
type ProjectToTag = ::zerocopy::pointer::cast::CastToUnit;
17591793
#[inline(always)]
17601794
fn project(
17611795
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -1837,6 +1871,8 @@ const _: () = {
18371871
{
18381872
fn only_derive_is_allowed_to_implement_this_trait() {}
18391873
type Type = u8;
1874+
type Tag = ___ZerocopyTag;
1875+
type ProjectToTag = ::zerocopy::pointer::cast::CastSized;
18401876
#[inline(always)]
18411877
fn project(
18421878
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -1949,6 +1985,8 @@ const _: () = {
19491985
{
19501986
fn only_derive_is_allowed_to_implement_this_trait() {}
19511987
type Type = X;
1988+
type Tag = ___ZerocopyTag;
1989+
type ProjectToTag = ::zerocopy::pointer::cast::CastSized;
19521990
#[inline(always)]
19531991
fn project(
19541992
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -2061,6 +2099,8 @@ const _: () = {
20612099
{
20622100
fn only_derive_is_allowed_to_implement_this_trait() {}
20632101
type Type = X::Target;
2102+
type Tag = ___ZerocopyTag;
2103+
type ProjectToTag = ::zerocopy::pointer::cast::CastSized;
20642104
#[inline(always)]
20652105
fn project(
20662106
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -2173,6 +2213,8 @@ const _: () = {
21732213
{
21742214
fn only_derive_is_allowed_to_implement_this_trait() {}
21752215
type Type = Y::Target;
2216+
type Tag = ___ZerocopyTag;
2217+
type ProjectToTag = ::zerocopy::pointer::cast::CastSized;
21762218
#[inline(always)]
21772219
fn project(
21782220
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -2285,6 +2327,8 @@ const _: () = {
22852327
{
22862328
fn only_derive_is_allowed_to_implement_this_trait() {}
22872329
type Type = [(X, Y); N];
2330+
type Tag = ___ZerocopyTag;
2331+
type ProjectToTag = ::zerocopy::pointer::cast::CastSized;
22882332
#[inline(always)]
22892333
fn project(
22902334
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -2397,6 +2441,8 @@ const _: () = {
23972441
{
23982442
fn only_derive_is_allowed_to_implement_this_trait() {}
23992443
type Type = bool;
2444+
type Tag = ___ZerocopyTag;
2445+
type ProjectToTag = ::zerocopy::pointer::cast::CastSized;
24002446
#[inline(always)]
24012447
fn project(
24022448
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -2509,6 +2555,8 @@ const _: () = {
25092555
{
25102556
fn only_derive_is_allowed_to_implement_this_trait() {}
25112557
type Type = Y;
2558+
type Tag = ___ZerocopyTag;
2559+
type ProjectToTag = ::zerocopy::pointer::cast::CastSized;
25122560
#[inline(always)]
25132561
fn project(
25142562
slf: ::zerocopy::pointer::PtrInner<'_, Self>,
@@ -2621,6 +2669,8 @@ const _: () = {
26212669
{
26222670
fn only_derive_is_allowed_to_implement_this_trait() {}
26232671
type Type = PhantomData<&'a [(X, Y); N]>;
2672+
type Tag = ___ZerocopyTag;
2673+
type ProjectToTag = ::zerocopy::pointer::cast::CastSized;
26242674
#[inline(always)]
26252675
fn project(
26262676
slf: ::zerocopy::pointer::PtrInner<'_, Self>,

0 commit comments

Comments
 (0)