mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
Rust fixes for v7.0 (2nd)
Toolchain and infrastructure:
- Remap paths to avoid absolute ones starting with the upcoming Rust
1.95.0 release. This improves build reproducibility, avoids leaking
the exact path and avoids having the same path appear in two forms.
The approach here avoids remapping debug information as well, in
order to avoid breaking tools that used the paths to access source
files, which was the previous attempt that needed to be reverted.
- Allow 'unused_features' lint for the upcoming Rust 1.96.0 release.
While well-intentioned, we do not benefit much from the new lint.
- Emit dependency information into '$(depfile)' directly to avoid
a temporary '.d' file (it was an old approach).
'kernel' crate:
- 'str' module: fix warning under '!CONFIG_BLOCK' by making
'NullTerminatedFormatter' public.
- 'cpufreq' module: suppress false positive Clippy warning.
'pin-init' crate:
- Remove '#[disable_initialized_field_access]' attribute which was
unsound. This means removing the support for structs with unaligned
fields (through the 'repr(packed)' attribute), for now.
And document the load-bearing fact of field accessors (i.e. that they
are required for soundness).
- Replace shadowed return token by 'unsafe'-to-create token in order
to remain sound in the face of the likely upcoming Type Alias Impl
Trait (TAIT) and the next trait solver in upstream Rust.
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEPjU5OPd5QIZ9jqqOGXyLc2htIW0FAmm1r2MACgkQGXyLc2ht
IW17OhAAoRMLTOf/iTNu29njOtjG5iYABeC5zMnxYUErWGLOooz8D82UEiB85Whs
uhVeW6YZ1jCcizglmbXOduKUOmSvEUYSv5/wj1w5OIF0FWW/6BA/aNdgDijHTbSU
v/x5NfKwxZ7JD8ivl+Z7RxtA3ggEODr/pn8USIKaZr0wEjEcnP1xBedZR6+NXuBT
CUXYm9g0BMfBbHsaI6DgD6/aj3TuHjbp1GGFlMmKd7YJGzFihhxU7nKtzkRDxAUd
HROY1Pi+iEUXFYmeXbgObVgRqzcTYV37CkbMfPk1SoIdXXhtPcO8TJ1GguAMuVMO
alAaVEAGFBKvnNGFoocCoxRt8U9hhiOiqlP+QMu2sbVWxWdmdBRcXlB+t4YIqFWy
6Icp/5K8C6Tf7ZrDZhccn6T6jqp+mvNzfanppi0/DFlZiN+1oSABQgEV3YtAiEIW
UHLT5bO5YEkHW73S9mSKhBhbH58h8IX7oGv/wteovI3gjMA9of/8/6MArWXbLpxj
o6ws7p595/xRV+xZURm7YQm6wtbjBr4Eipgd3vIoc0Z+VbCnDLEs/n8cEYY2CtIg
9Ze+MbBaqnf58qvhwj9Zy8ncQVnCtpQmybUE/i/YfdXo7AMsKtdUppv09xfz4fMC
NWRqJttuWiUttGsLvi/GTxzkz5bT6Y6ZHHNqTyIKWXEIBTtRxK8=
=7LgC
-----END PGP SIGNATURE-----
Merge tag 'rust-fixes-7.0-2' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux
Pull Rust fixes from Miguel Ojeda:
"Toolchain and infrastructure:
- Remap paths to avoid absolute ones starting with the upcoming Rust
1.95.0 release. This improves build reproducibility, avoids leaking
the exact path and avoids having the same path appear in two forms
The approach here avoids remapping debug information as well, in
order to avoid breaking tools that used the paths to access source
files, which was the previous attempt that needed to be reverted
- Allow 'unused_features' lint for the upcoming Rust 1.96.0 release.
While well-intentioned, we do not benefit much from the new lint
- Emit dependency information into '$(depfile)' directly to avoid a
temporary '.d' file (it was an old approach)
'kernel' crate:
- 'str' module: fix warning under '!CONFIG_BLOCK' by making
'NullTerminatedFormatter' public
- 'cpufreq' module: suppress false positive Clippy warning
'pin-init' crate:
- Remove '#[disable_initialized_field_access]' attribute which was
unsound. This means removing the support for structs with unaligned
fields (through the 'repr(packed)' attribute), for now
And document the load-bearing fact of field accessors (i.e. that
they are required for soundness)
- Replace shadowed return token by 'unsafe'-to-create token in order
to remain sound in the face of the likely upcoming Type Alias Impl
Trait (TAIT) and the next trait solver in upstream Rust"
* tag 'rust-fixes-7.0-2' of git://git.kernel.org/pub/scm/linux/kernel/git/ojeda/linux:
rust: kbuild: allow `unused_features`
rust: cpufreq: suppress clippy::double_parens in Policy doctest
rust: pin-init: replace shadowed return token by `unsafe`-to-create token
rust: pin-init: internal: init: document load-bearing fact of field accessors
rust: pin-init: internal: init: remove `#[disable_initialized_field_access]`
rust: build: remap path to avoid absolute path
rust: kbuild: emit dep-info into $(depfile) directly
rust: str: make NullTerminatedFormatter public
This commit is contained in:
commit
267594792a
4
Makefile
4
Makefile
|
|
@ -476,6 +476,7 @@ KBUILD_USERLDFLAGS := $(USERLDFLAGS)
|
|||
export rust_common_flags := --edition=2021 \
|
||||
-Zbinary_dep_depinfo=y \
|
||||
-Astable_features \
|
||||
-Aunused_features \
|
||||
-Dnon_ascii_idents \
|
||||
-Dunsafe_op_in_unsafe_fn \
|
||||
-Wmissing_docs \
|
||||
|
|
@ -1113,6 +1114,9 @@ KBUILD_CFLAGS += -fno-builtin-wcslen
|
|||
# change __FILE__ to the relative path to the source directory
|
||||
ifdef building_out_of_srctree
|
||||
KBUILD_CPPFLAGS += -fmacro-prefix-map=$(srcroot)/=
|
||||
ifeq ($(call rustc-option-yn, --remap-path-scope=macro),y)
|
||||
KBUILD_RUSTFLAGS += --remap-path-prefix=$(srcroot)/= --remap-path-scope=macro
|
||||
endif
|
||||
endif
|
||||
|
||||
# include additional Makefiles when needed
|
||||
|
|
|
|||
|
|
@ -148,7 +148,8 @@ doctests_modifiers_workaround := $(rustdoc_modifiers_workaround)$(if $(call rust
|
|||
quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $<
|
||||
cmd_rustdoc = \
|
||||
OBJTREE=$(abspath $(objtree)) \
|
||||
$(RUSTDOC) $(filter-out $(skip_flags) --remap-path-prefix=%,$(if $(rustdoc_host),$(rust_common_flags),$(rust_flags))) \
|
||||
$(RUSTDOC) $(filter-out $(skip_flags) --remap-path-prefix=% --remap-path-scope=%, \
|
||||
$(if $(rustdoc_host),$(rust_common_flags),$(rust_flags))) \
|
||||
$(rustc_target_flags) -L$(objtree)/$(obj) \
|
||||
-Zunstable-options --generate-link-to-definition \
|
||||
--output $(rustdoc_output) \
|
||||
|
|
@ -334,7 +335,7 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
|
|||
rm -rf $(objtree)/$(obj)/test/doctests/kernel; \
|
||||
mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \
|
||||
OBJTREE=$(abspath $(objtree)) \
|
||||
$(RUSTDOC) --test $(filter-out --remap-path-prefix=%,$(rust_flags)) \
|
||||
$(RUSTDOC) --test $(filter-out --remap-path-prefix=% --remap-path-scope=%,$(rust_flags)) \
|
||||
-L$(objtree)/$(obj) --extern ffi --extern pin_init \
|
||||
--extern kernel --extern build_error --extern macros \
|
||||
--extern bindings --extern uapi \
|
||||
|
|
@ -526,11 +527,9 @@ quiet_cmd_rustc_procmacrolibrary = $(RUSTC_OR_CLIPPY_QUIET) PL $@
|
|||
cmd_rustc_procmacrolibrary = \
|
||||
$(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \
|
||||
$(filter-out $(skip_flags),$(rust_common_flags) $(rustc_target_flags)) \
|
||||
--emit=dep-info,link --crate-type rlib -O \
|
||||
--emit=dep-info=$(depfile) --emit=link=$@ --crate-type rlib -O \
|
||||
--out-dir $(objtree)/$(obj) -L$(objtree)/$(obj) \
|
||||
--crate-name $(patsubst lib%.rlib,%,$(notdir $@)) $<; \
|
||||
mv $(objtree)/$(obj)/$(patsubst lib%.rlib,%,$(notdir $@)).d $(depfile); \
|
||||
sed -i '/^\#/d' $(depfile)
|
||||
--crate-name $(patsubst lib%.rlib,%,$(notdir $@)) $<
|
||||
|
||||
$(obj)/libproc_macro2.rlib: private skip_clippy = 1
|
||||
$(obj)/libproc_macro2.rlib: private rustc_target_flags = $(proc_macro2-flags)
|
||||
|
|
|
|||
|
|
@ -401,6 +401,7 @@ pub fn to_table(mut self) -> Result<TableBox> {
|
|||
/// ```
|
||||
/// use kernel::cpufreq::{DEFAULT_TRANSITION_LATENCY_NS, Policy};
|
||||
///
|
||||
/// #[allow(clippy::double_parens, reason = "False positive before 1.92.0")]
|
||||
/// fn update_policy(policy: &mut Policy) {
|
||||
/// policy
|
||||
/// .set_dvfs_possible_from_any_cpu(true)
|
||||
|
|
|
|||
|
|
@ -664,13 +664,13 @@ fn write_str(&mut self, s: &str) -> fmt::Result {
|
|||
///
|
||||
/// * The first byte of `buffer` is always zero.
|
||||
/// * The length of `buffer` is at least 1.
|
||||
pub(crate) struct NullTerminatedFormatter<'a> {
|
||||
pub struct NullTerminatedFormatter<'a> {
|
||||
buffer: &'a mut [u8],
|
||||
}
|
||||
|
||||
impl<'a> NullTerminatedFormatter<'a> {
|
||||
/// Create a new [`Self`] instance.
|
||||
pub(crate) fn new(buffer: &'a mut [u8]) -> Option<NullTerminatedFormatter<'a>> {
|
||||
pub fn new(buffer: &'a mut [u8]) -> Option<NullTerminatedFormatter<'a>> {
|
||||
*(buffer.first_mut()?) = 0;
|
||||
|
||||
// INVARIANT:
|
||||
|
|
|
|||
|
|
@ -62,7 +62,6 @@ fn ident(&self) -> Option<&Ident> {
|
|||
|
||||
enum InitializerAttribute {
|
||||
DefaultError(DefaultErrorAttribute),
|
||||
DisableInitializedFieldAccess,
|
||||
}
|
||||
|
||||
struct DefaultErrorAttribute {
|
||||
|
|
@ -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 {
|
||||
|
|
@ -145,22 +145,9 @@ fn assert_zeroable<T: ?::core::marker::Sized>(_: *mut T)
|
|||
};
|
||||
// `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
|
||||
// type and shadow it later when we insert the arbitrary user code. That way there will be
|
||||
// no possibility of returning without `unsafe`.
|
||||
struct __InitOk;
|
||||
|
||||
// Get the data about fields from the supplied type.
|
||||
// SAFETY: TODO
|
||||
let #data = unsafe {
|
||||
|
|
@ -170,18 +157,15 @@ fn assert_zeroable<T: ?::core::marker::Sized>(_: *mut T)
|
|||
#path::#get_data()
|
||||
};
|
||||
// Ensure that `#data` really is of type `#data` and help with type inference:
|
||||
let init = ::pin_init::__internal::#data_trait::make_closure::<_, __InitOk, #error>(
|
||||
let init = ::pin_init::__internal::#data_trait::make_closure::<_, #error>(
|
||||
#data,
|
||||
move |slot| {
|
||||
{
|
||||
// Shadow the structure so it cannot be used to return early.
|
||||
struct __InitOk;
|
||||
#zeroable_check
|
||||
#this
|
||||
#init_fields
|
||||
#field_check
|
||||
}
|
||||
Ok(__InitOk)
|
||||
#zeroable_check
|
||||
#this
|
||||
#init_fields
|
||||
#field_check
|
||||
// SAFETY: we are the `init!` macro that is allowed to call this.
|
||||
Ok(unsafe { ::pin_init::__internal::InitOk::new() })
|
||||
}
|
||||
);
|
||||
let init = move |slot| -> ::core::result::Result<(), #error> {
|
||||
|
|
@ -236,7 +220,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 {
|
||||
|
|
@ -260,6 +243,10 @@ 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 field is properly aligned.
|
||||
// Unaligned fields will cause the compiler to emit E0793. We do not support
|
||||
// unaligned fields since `Init::__init` requires an aligned pointer; the call to
|
||||
// `ptr::write` below has the same requirement.
|
||||
let accessor = if pinned {
|
||||
let project_ident = format_ident!("__project_{ident}");
|
||||
quote! {
|
||||
|
|
@ -272,13 +259,6 @@ fn init_fields(
|
|||
unsafe { &mut (*#slot).#ident }
|
||||
}
|
||||
};
|
||||
let accessor = generate_initialized_accessors.then(|| {
|
||||
quote! {
|
||||
#(#cfgs)*
|
||||
#[allow(unused_variables)]
|
||||
let #ident = #accessor;
|
||||
}
|
||||
});
|
||||
quote! {
|
||||
#(#attrs)*
|
||||
{
|
||||
|
|
@ -286,12 +266,18 @@ fn init_fields(
|
|||
// 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 field is properly aligned.
|
||||
// Unaligned fields will cause the compiler to emit E0793. We do not support
|
||||
// unaligned fields since `Init::__init` requires an aligned pointer; the call to
|
||||
// `ptr::write` below has the same requirement.
|
||||
let (value_init, accessor) = if pinned {
|
||||
let project_ident = format_ident!("__project_{ident}");
|
||||
(
|
||||
|
|
@ -326,20 +312,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! {
|
||||
|
|
@ -466,10 +447,6 @@ fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
|
|||
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"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,24 @@ unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), E> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Token type to signify successful initialization.
|
||||
///
|
||||
/// Can only be constructed via the unsafe [`Self::new`] function. The initializer macros use this
|
||||
/// token type to prevent returning `Ok` from an initializer without initializing all fields.
|
||||
pub struct InitOk(());
|
||||
|
||||
impl InitOk {
|
||||
/// Creates a new token.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function may only be called from the `init!` macro in `../internal/src/init.rs`.
|
||||
#[inline(always)]
|
||||
pub unsafe fn new() -> Self {
|
||||
Self(())
|
||||
}
|
||||
}
|
||||
|
||||
/// This trait is only implemented via the `#[pin_data]` proc-macro. It is used to facilitate
|
||||
/// the pin projections within the initializers.
|
||||
///
|
||||
|
|
@ -68,9 +86,10 @@ pub unsafe trait PinData: Copy {
|
|||
type Datee: ?Sized + HasPinData;
|
||||
|
||||
/// Type inference helper function.
|
||||
fn make_closure<F, O, E>(self, f: F) -> F
|
||||
#[inline(always)]
|
||||
fn make_closure<F, E>(self, f: F) -> F
|
||||
where
|
||||
F: FnOnce(*mut Self::Datee) -> Result<O, E>,
|
||||
F: FnOnce(*mut Self::Datee) -> Result<InitOk, E>,
|
||||
{
|
||||
f
|
||||
}
|
||||
|
|
@ -98,9 +117,10 @@ pub unsafe trait InitData: Copy {
|
|||
type Datee: ?Sized + HasInitData;
|
||||
|
||||
/// Type inference helper function.
|
||||
fn make_closure<F, O, E>(self, f: F) -> F
|
||||
#[inline(always)]
|
||||
fn make_closure<F, E>(self, f: F) -> F
|
||||
where
|
||||
F: FnOnce(*mut Self::Datee) -> Result<O, E>,
|
||||
F: FnOnce(*mut Self::Datee) -> Result<InitOk, E>,
|
||||
{
|
||||
f
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user