-
Notifications
You must be signed in to change notification settings - Fork 76
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
Remove NoCell
bounds emitted by derive(TryFromBytes)
on unions
#1016
Conversation
acf1c98
to
d0fae92
Compare
This isn't a problem for This isn't a problem for structs, because struct projections always respect that the projection has In the case of unions, projections do not have |
Imagine we had two validity checking methods instead of one: The derive implementation of fn derive_try_from_bytes_union(ast: &DeriveInput, unn: &DataUnion) -> proc_macro2::TokenStream {
let extras = Some({
let fields = unn.fields();
let field_names = fields.iter().map(|(name, _ty)| name);
let field_tys = fields.iter().map(|(_name, ty)| ty);
quote!(
fn is_bit_valid_shared(
mut candidate: ::zerocopy::Maybe<Self, ::zerocopy::invariant::Shared>
) -> bool
where
Self: NoCell,
{
false #(|| {
// SAFETY: `project` is a field projection of `candidate`,
// and `Self` is a union type. The candidate and projection
// agree on where their `UnsafeCell`s are, because `Self:
// NoCell`, and, by implication, the projected field is
// `NoCell`.
let field_candidate = unsafe {
let project = |slf: *mut Self|
::zerocopy::macro_util::core_reexport::ptr::addr_of_mut!((*slf).#field_names);
candidate.reborrow().project(project)
};
<#field_tys as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
})*
}
fn is_bit_valid_exclusive(
mut candidate: ::zerocopy::Maybe<Self, ::zerocopy::invariant::Exclusive>
) -> bool {
false #(|| {
// SAFETY: `project` is a field projection of `candidate`,
// and `Self` is a union type. The candidate and projection
// do not need to agree on exactly on where their
// `UnsafeCell` ranges are, because `candidate` is
// exclusively aliased.
let field_candidate = unsafe {
let project = |slf: *mut Self|
::zerocopy::macro_util::core_reexport::ptr::addr_of_mut!((*slf).#field_names);
candidate.reborrow().project(project)
};
<#field_tys as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
})*
}
)
});
impl_block(ast, unn, Trait::TryFromBytes, FieldBounds::ALL_SELF, SelfBounds::None, None, extras)
} The bodies of these methods are identical except for their differing SAFETY comments. |
46674af
to
1421250
Compare
ac8d329
to
d0fae92
Compare
d0fae92
to
d64eb4f
Compare
This PR applies the approach used to implement
is_bit_valid
forUnsafeCell
to unions. However, it's not entirely satisfactory in this case. Yes, it enables us to remove theNoCell
field bounds fromderive(TryFromBytes)
on unions. Unfortunately, it also makesis_bit_valid
uncallable byTryFromBytes::try_from_ref
, even whenSelf: NoCell
.Maybe we can apply an approach similar to the one used to solve #1014 to handle this.
Makes progress towards #5.
Closes #1015.