-
Notifications
You must be signed in to change notification settings - Fork 104
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
Make derive macros hygienic #11
Comments
TODO: - What does doing `::core` buy us over `core`? - Doesn't seem like we can do `::zerocopy` since zerocopy itself defines a `zerocopy` module at the top level which is meant to mimic the `zerocopy` that the emitted code expects; however, are we losing anything by not doing `::zerocopy`? Part of #11
@Kestrer, do you know if it's sufficient to instead emit Another approach that occurred to me - which I suspect also won't work for some reason - is to emit |
@djkoloski Flagging this in case you'd be interested in it - specifically the |
This should be the default option, since in most cases it works. However, it fails in the following cases:
Supporting these cases is the motivation for adding a
I believe that also fails in the two cases listed above. |
Turns out `rkyv` is more for defining a new binary encoding scheme rather than reusing an existing one (which is the main purpose of zorua). So, replacing it with the `zerocopy` crate. - Reexported items from the zerocopy crate for to/from bytes traits. - Also reexported endian-aware int/float types via the byteorder feature of zerocopy. - Unfortunately, until google/zerocopy#11 is resolved, downstream must also import the zerocopy crate (ideally of the same minor version).
Turns out `rkyv` is more for defining a new binary encoding scheme rather than reusing an existing one (which is the main purpose of zorua). So, replacing it with the `zerocopy` crate. - Reexported items from the zerocopy crate for to/from bytes traits. - Also reexported endian-aware int/float types via the byteorder feature of zerocopy. - Unfortunately, until google/zerocopy#11 is resolved, downstream must also import the zerocopy crate (ideally of the same minor version).
Turns out `rkyv` is more for defining a new binary encoding scheme rather than reusing an existing one (which is the main purpose of zorua). So, replacing it with the `zerocopy` crate. - Reexported items from the zerocopy crate for to/from bytes traits. - Also reexported endian-aware int/float types via the byteorder feature of zerocopy. - Unfortunately, until google/zerocopy#11 is resolved, downstream must also import the zerocopy crate (ideally of the same minor version).
Turns out `rkyv` is more for defining a new binary encoding scheme rather than reusing an existing one (which is the main purpose of zorua). So, replacing it with the `zerocopy` crate. - Reexported items from the zerocopy crate for to/from bytes traits. - Also reexported endian-aware int/float types via the byteorder feature of zerocopy. - Unfortunately, until google/zerocopy#11 is resolved, downstream must also import the zerocopy crate (ideally of the same minor version).
This has the effect of ensuring that derive-emitted code will fail to compile if it spuriously relies on certain identifiers being in scope - namely, identifiers which are part of the prelude. Disabling the prelude surfaced a few bugs which are also fixed in this commit. Makes progress on #11
This has the effect of ensuring that derive-emitted code will fail to compile if it spuriously relies on certain identifiers being in scope - namely, identifiers which are part of the prelude. Disabling the prelude surfaced a few bugs which are also fixed in this commit. Makes progress on #11
This has the effect of ensuring that derive-emitted code will fail to compile if it spuriously relies on certain identifiers being in scope - namely, identifiers which are part of the prelude. Disabling the prelude surfaced a few bugs which are also fixed in this commit. Makes progress on #11
This has the effect of ensuring that derive-emitted code will fail to compile if it spuriously relies on certain identifiers being in scope - namely, identifiers which are part of the prelude. Disabling the prelude surfaced a few bugs which are also fixed in this commit. Makes progress on #11
This has the effect of ensuring that derive-emitted code will fail to compile if it spuriously relies on certain identifiers being in scope - namely, identifiers which are part of the prelude. Disabling the prelude surfaced a few bugs which are also fixed in this commit. Makes progress on #11
This has the effect of ensuring that derive-emitted code will fail to compile if it spuriously relies on certain identifiers being in scope - namely, identifiers which are part of the prelude. Disabling the prelude surfaced a few bugs which are also fixed in this commit. Makes progress on #11
This has the effect of ensuring that derive-emitted code will fail to compile if it spuriously relies on certain identifiers being in scope - namely, identifiers which are part of the prelude. Disabling the prelude surfaced a few bugs which are also fixed in this commit. Makes progress on #11
This has the effect of ensuring that derive-emitted code will fail to compile if it spuriously relies on certain identifiers being in scope - namely, identifiers which are part of the prelude. Disabling the prelude surfaced a few bugs which are also fixed in this commit. Makes progress on google#11
Turns out `rkyv` is more for defining a new binary encoding scheme rather than reusing an existing one (which is the main purpose of zorua). So, replacing it with the `zerocopy` crate. - Reexported items from the zerocopy crate for to/from bytes traits. - Also reexported endian-aware int/float types via the byteorder feature of zerocopy. - Unfortunately, until google/zerocopy#11 is resolved, downstream must also import the zerocopy crate (ideally of the same minor version).
Turns out `rkyv` is more for defining a new binary encoding scheme rather than reusing an existing one (which is the main purpose of zorua). So, replacing it with the `zerocopy` crate. - Reexported items from the zerocopy crate for to/from bytes traits. - Also reexported endian-aware int/float types via the byteorder feature of zerocopy. - Unfortunately, until google/zerocopy#11 is resolved, downstream must also import the zerocopy crate (ideally of the same minor version).
I am not sure what constraints you have on dependencies, but there is a crate, |
rkyv also has a |
Merging #619 (authored by @jswrenn) into this There are a number of high-profile crates in the Rust ecosystem that define types whose memory representation is part of their documented contract. By implementing zerocopy's traits for these types, their users could benefit from zerocopy's compiler-time checks that operations depending on these contracts are sound. But: Where should these trait implementations go? It is risky for zerocopy to provide trait implementations on foreign types, since zerocopy cannot check the soundness of its implementations on foreign types. If zerocopy's trait implementations implementations on foreign types fell out of sync with the definitions of those types, unsoundness would ensue. It is strictly safer for third-party types to provide their own implementations of zerocopy's traits, using zerocopy's
Both of these options adds friction to the adoption of zerocopy in the Rust ecosystem. Proposed SolutionThere exists a third not-yet-quite-possible-today option: Provided multi-versioned support for zerocopy. A customer taking this approach would specify a new optional dependency for each version of zerocopy they support; e.g., they would start with: [dependencies]
zerocopy_0_7 = { package = "zerocopy", version = "0.7", optional = true, features = ["derive"] } ...and provide feature-gated implementations for that version: #[cfg_attr(
feature = "zerocopy_0_7",
derive(
zerocopy_0_7::FromZeroes,
zerocopy_0_7::FromBytes,
zerocopy_0_7::AsBytes
),
zerocopy_0_7(root = ::zerocopy_0_7),
)]
#[repr(C)]
pub struct sembuf {
pub sem_num: c_ushort,
pub sem_op: c_short,
pub sem_flg: c_short,
} Upon a new major release of zerocopy, the customer could append a new version to their [dependencies]
zerocopy_0_7 = { package = "zerocopy", version = "0.7", optional = true, features = ["derive"] }
+ zerocopy_0_8 = { package = "zerocopy", version = "0.8", optional = true, features = ["derive"] } ...and add new, corresponding feature-gated derives: #[cfg_attr(
feature = "zerocopy_0_7",
derive(
zerocopy_0_7::FromZeroes,
zerocopy_0_7::FromBytes,
zerocopy_0_7::AsBytes
),
)]
+ #[cfg_attr(
+ feature = "zerocopy_0_8",
+ derive(
+ zerocopy_0_8::KnownLayout,
+ zerocopy_0_8::TryFromBytes,
+ zerocopy_0_8::FromZeroes,
+ zerocopy_0_8::FromBytes,
+ zerocopy_0_8::AsBytes
+ ),
+ )]
#[repr(C)]
pub struct sembuf {
pub sem_num: c_ushort,
pub sem_op: c_short,
pub sem_flg: c_short,
} Technical DetailsPresently, zerocopy's derives unconditionally expand to code referencing the path 1. Root-setting helper attribute.Zerocopy could provide a helper attribute for setting its crate root; e.g.: #[cfg_attr(
feature = "zerocopy_0_7",
derive(
zerocopy_0_7::FromZeroes,
zerocopy_0_7::FromBytes,
zerocopy_0_7::AsBytes
),
zerocopy_0_7(crate = ::zerocopy_0_7), // <--- this
)] The attribute would instruct zerocopy's derives to expand to paths beginning with The drawback of this approach is that this attribute adds line noise to critical derives. 2. Re-export old versionsAlternatively, zerocopy could optionally depend on older versions of itself: [dependencies]
# ...
v_0_6 = { package = "zerocopy", version = "0.6", optional = true }
# ... ...and provide versioned re-exports of itself at its root: #[doc(hidden)]
mod version {
pub use super:: as v0_7;
#[cfg(feature = "v_0_6")]
pub use ::v_0_6;
} We would then modify zerocopy's derives to always expand to paths beginning with Unresolved question: In this approach, how would we populate the |
Status
core
items are referenced as::core::xxx
rather thancore::xxx
#[zerocopy(crate = "...")]
annotation#[zerocopy_rename]
annotation#[zerocopy(crate = "...", derive-version = "...")]
annotationCrate name annotation
Sometimes, our derives will be used in a context in which
zerocopy
isn't calledzerocopy
. For example, this might happen if zerocopy itself is re-exported from another crate, or if a crate wishes to support deriving zerocopy traits from multiple zerocopy versions (see e.g. #557).We can take inspiration from Serde, which defines the
crate
attribute option:#[serde(crate = "...")]
In other words, we can do:
#[zerocopy(crate = "...")]
However, this isn't enough. For users who wish to invoke derives from multiple versions of zerocopy-derive at once, we need a way of disambiguating which attributes are meant to be consumed by which version of zerocopy-derive. We could provide a disambiguation option like so:
#[zerocopy(crate = "...", derive-version = "...")]
This would let us write code like the following (from #557):
In this example, each
zerocopy-derive
would usederive-version
to filter out attributes not meant for that version.Simpler alternative
The above-described design is a bit complex, and requires users to add a new attribute for each zerocopy version. This is especially painful for crates like libc who will have hundreds of uses.
An alternative is to not permit the user to specify the name of the crate, but instead only support a single naming scheme:
This has the same semantics as the preceding example, but it assumes that for zerocopy-derive 0.X.Y, the
zerocopy
crate is imported aszerocopy_X_Y
, and for zerocopy-derive X.Y.Z, thatzerocopy
is imported aszerocopy_X
.Core re-export
We can't rely on
core
being in scope (or referring to the "real"core
crate). However, we can rely onzerocopy
being in scope (possibly renamed, as described above). If we re-exportcore
fromzerocopy
, then we can emit code that doesn't refer to::core
, but instead refers to::zerocopy::core_reexport
.Mentoring instructions
Interested in contributing? See our contributing guide.
This issue can be tackled in a number of discrete steps. Progress on any one of these would be fantastic, so don't feel like you need to tackle the whole thing!
#[zerocopy(crate = "...")]
annotation similar to serde's#[zerocopy_rename]
annotation as described above#[zerocopy(crate = "...", derive-version = "...")]
annotation as described aboveThe text was updated successfully, but these errors were encountered: