Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `[pin_]init!` now supports attributes on fields (such as `#[cfg(...)]`).
- Add a `#[default_error(<type>)]` attribute to `[pin_]init!` to override the
default error (when no `? Error` is specified).
- Support packed struct in `[pin_]init!` with `#[disable_initialized_field_access]`.

### Removed

Expand Down
49 changes: 18 additions & 31 deletions internal/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ impl InitializerKind {

enum InitializerAttribute {
DefaultError(DefaultErrorAttribute),
DisableInitializedFieldAccess,
}

struct DefaultErrorAttribute {
Expand All @@ -86,6 +85,7 @@ pub(crate) fn expand(
let error = error.map_or_else(
|| {
if let Some(default_error) = attrs.iter().fold(None, |acc, attr| {
#[expect(irrefutable_let_patterns)]
if let InitializerAttribute::DefaultError(DefaultErrorAttribute { ty }) = attr {
Some(ty.clone())
} else {
Expand Down Expand Up @@ -145,15 +145,7 @@ pub(crate) fn expand(
};
// `mixed_site` ensures that the data is not accessible to the user-controlled code.
let data = Ident::new("__data", Span::mixed_site());
let init_fields = init_fields(
&fields,
pinned,
!attrs
.iter()
.any(|attr| matches!(attr, InitializerAttribute::DisableInitializedFieldAccess)),
&data,
&slot,
);
let init_fields = init_fields(&fields, pinned, &data, &slot);
let field_check = make_field_check(&fields, init_kind, &path);
Ok(quote! {{
// We do not want to allow arbitrary returns, so we declare this type as the `Ok` return
Expand Down Expand Up @@ -242,7 +234,6 @@ fn get_init_kind(rest: Option<(Token![..], Expr)>, dcx: &mut DiagCtxt) -> InitKi
fn init_fields(
fields: &Punctuated<InitializerField, Token![,]>,
pinned: bool,
generate_initialized_accessors: bool,
data: &Ident,
slot: &Ident,
) -> TokenStream {
Expand All @@ -266,6 +257,11 @@ fn init_fields(
});
// Again span for better diagnostics
let write = quote_spanned!(ident.span()=> ::core::ptr::write);
// NOTE: the field accessor ensures that the initialized struct is not
// `repr(packed)`. If it were, the compiler would emit E0793. We do not support
// packed structs, since `Init::__init` requires an aligned pointer; the same
// requirement that the call to `ptr::write` below has.
// For more info see <https://github.com/Rust-for-Linux/pin-init/issues/112>
let accessor = if pinned {
let project_ident = format_ident!("__project_{ident}");
quote! {
Expand All @@ -278,26 +274,26 @@ fn init_fields(
unsafe { &mut (*#slot).#ident }
}
};
let accessor = generate_initialized_accessors.then(|| {
quote! {
#(#cfgs)*
#[allow(unused_variables)]
let #ident = #accessor;
}
});
quote! {
#(#attrs)*
{
#value_prep
// SAFETY: TODO
unsafe { #write(::core::ptr::addr_of_mut!((*#slot).#ident), #value_ident) };
}
#accessor
#(#cfgs)*
#[allow(unused_variables)]
let #ident = #accessor;
}
}
InitializerKind::Init { ident, value, .. } => {
// Again span for better diagnostics
let init = format_ident!("init", span = value.span());
// NOTE: the field accessor ensures that the initialized struct is not
// `repr(packed)`. If it were, the compiler would emit E0793. We do not support
// packed structs, since `Init::__init` requires an aligned pointer; the same
// requirement that the call to `ptr::write` below has.
// For more info see <https://github.com/Rust-for-Linux/pin-init/issues/112>
let (value_init, accessor) = if pinned {
let project_ident = format_ident!("__project_{ident}");
(
Expand Down Expand Up @@ -332,20 +328,15 @@ fn init_fields(
},
)
};
let accessor = generate_initialized_accessors.then(|| {
quote! {
#(#cfgs)*
#[allow(unused_variables)]
let #ident = #accessor;
}
});
quote! {
#(#attrs)*
{
let #init = #value;
#value_init
}
#accessor
#(#cfgs)*
#[allow(unused_variables)]
let #ident = #accessor;
}
}
InitializerKind::Code { block: value, .. } => quote! {
Expand Down Expand Up @@ -472,10 +463,6 @@ impl Parse for Initializer {
if a.path().is_ident("default_error") {
a.parse_args::<DefaultErrorAttribute>()
.map(InitializerAttribute::DefaultError)
} else if a.path().is_ident("disable_initialized_field_access") {
a.meta
.require_path_only()
.map(|_| InitializerAttribute::DisableInitializedFieldAccess)
} else {
Err(syn::Error::new_spanned(a, "unknown initializer attribute"))
}
Expand Down
19 changes: 0 additions & 19 deletions tests/ui/compile-fail/init/no_field_access.rs

This file was deleted.

5 changes: 0 additions & 5 deletions tests/ui/compile-fail/init/no_field_access.stderr

This file was deleted.

76 changes: 0 additions & 76 deletions tests/ui/expand/no_field_access.expanded.rs

This file was deleted.

1 change: 0 additions & 1 deletion tests/ui/expand/no_field_access.rs

This file was deleted.