mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
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:
4
Makefile
4
Makefile
@@ -476,6 +476,7 @@ KBUILD_USERLDFLAGS := $(USERLDFLAGS)
|
|||||||
export rust_common_flags := --edition=2021 \
|
export rust_common_flags := --edition=2021 \
|
||||||
-Zbinary_dep_depinfo=y \
|
-Zbinary_dep_depinfo=y \
|
||||||
-Astable_features \
|
-Astable_features \
|
||||||
|
-Aunused_features \
|
||||||
-Dnon_ascii_idents \
|
-Dnon_ascii_idents \
|
||||||
-Dunsafe_op_in_unsafe_fn \
|
-Dunsafe_op_in_unsafe_fn \
|
||||||
-Wmissing_docs \
|
-Wmissing_docs \
|
||||||
@@ -1113,6 +1114,9 @@ KBUILD_CFLAGS += -fno-builtin-wcslen
|
|||||||
# change __FILE__ to the relative path to the source directory
|
# change __FILE__ to the relative path to the source directory
|
||||||
ifdef building_out_of_srctree
|
ifdef building_out_of_srctree
|
||||||
KBUILD_CPPFLAGS += -fmacro-prefix-map=$(srcroot)/=
|
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
|
endif
|
||||||
|
|
||||||
# include additional Makefiles when needed
|
# 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, ) $<
|
quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $<
|
||||||
cmd_rustdoc = \
|
cmd_rustdoc = \
|
||||||
OBJTREE=$(abspath $(objtree)) \
|
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) \
|
$(rustc_target_flags) -L$(objtree)/$(obj) \
|
||||||
-Zunstable-options --generate-link-to-definition \
|
-Zunstable-options --generate-link-to-definition \
|
||||||
--output $(rustdoc_output) \
|
--output $(rustdoc_output) \
|
||||||
@@ -334,7 +335,7 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
|
|||||||
rm -rf $(objtree)/$(obj)/test/doctests/kernel; \
|
rm -rf $(objtree)/$(obj)/test/doctests/kernel; \
|
||||||
mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \
|
mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \
|
||||||
OBJTREE=$(abspath $(objtree)) \
|
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 \
|
-L$(objtree)/$(obj) --extern ffi --extern pin_init \
|
||||||
--extern kernel --extern build_error --extern macros \
|
--extern kernel --extern build_error --extern macros \
|
||||||
--extern bindings --extern uapi \
|
--extern bindings --extern uapi \
|
||||||
@@ -526,11 +527,9 @@ quiet_cmd_rustc_procmacrolibrary = $(RUSTC_OR_CLIPPY_QUIET) PL $@
|
|||||||
cmd_rustc_procmacrolibrary = \
|
cmd_rustc_procmacrolibrary = \
|
||||||
$(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \
|
$(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \
|
||||||
$(filter-out $(skip_flags),$(rust_common_flags) $(rustc_target_flags)) \
|
$(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) \
|
--out-dir $(objtree)/$(obj) -L$(objtree)/$(obj) \
|
||||||
--crate-name $(patsubst lib%.rlib,%,$(notdir $@)) $<; \
|
--crate-name $(patsubst lib%.rlib,%,$(notdir $@)) $<
|
||||||
mv $(objtree)/$(obj)/$(patsubst lib%.rlib,%,$(notdir $@)).d $(depfile); \
|
|
||||||
sed -i '/^\#/d' $(depfile)
|
|
||||||
|
|
||||||
$(obj)/libproc_macro2.rlib: private skip_clippy = 1
|
$(obj)/libproc_macro2.rlib: private skip_clippy = 1
|
||||||
$(obj)/libproc_macro2.rlib: private rustc_target_flags = $(proc_macro2-flags)
|
$(obj)/libproc_macro2.rlib: private rustc_target_flags = $(proc_macro2-flags)
|
||||||
|
|||||||
@@ -401,6 +401,7 @@ impl TableBuilder {
|
|||||||
/// ```
|
/// ```
|
||||||
/// use kernel::cpufreq::{DEFAULT_TRANSITION_LATENCY_NS, Policy};
|
/// 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) {
|
/// fn update_policy(policy: &mut Policy) {
|
||||||
/// policy
|
/// policy
|
||||||
/// .set_dvfs_possible_from_any_cpu(true)
|
/// .set_dvfs_possible_from_any_cpu(true)
|
||||||
|
|||||||
@@ -664,13 +664,13 @@ impl fmt::Write for Formatter<'_> {
|
|||||||
///
|
///
|
||||||
/// * The first byte of `buffer` is always zero.
|
/// * The first byte of `buffer` is always zero.
|
||||||
/// * The length of `buffer` is at least 1.
|
/// * The length of `buffer` is at least 1.
|
||||||
pub(crate) struct NullTerminatedFormatter<'a> {
|
pub struct NullTerminatedFormatter<'a> {
|
||||||
buffer: &'a mut [u8],
|
buffer: &'a mut [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> NullTerminatedFormatter<'a> {
|
impl<'a> NullTerminatedFormatter<'a> {
|
||||||
/// Create a new [`Self`] instance.
|
/// 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;
|
*(buffer.first_mut()?) = 0;
|
||||||
|
|
||||||
// INVARIANT:
|
// INVARIANT:
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ impl InitializerKind {
|
|||||||
|
|
||||||
enum InitializerAttribute {
|
enum InitializerAttribute {
|
||||||
DefaultError(DefaultErrorAttribute),
|
DefaultError(DefaultErrorAttribute),
|
||||||
DisableInitializedFieldAccess,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DefaultErrorAttribute {
|
struct DefaultErrorAttribute {
|
||||||
@@ -86,6 +85,7 @@ pub(crate) fn expand(
|
|||||||
let error = error.map_or_else(
|
let error = error.map_or_else(
|
||||||
|| {
|
|| {
|
||||||
if let Some(default_error) = attrs.iter().fold(None, |acc, attr| {
|
if let Some(default_error) = attrs.iter().fold(None, |acc, attr| {
|
||||||
|
#[expect(irrefutable_let_patterns)]
|
||||||
if let InitializerAttribute::DefaultError(DefaultErrorAttribute { ty }) = attr {
|
if let InitializerAttribute::DefaultError(DefaultErrorAttribute { ty }) = attr {
|
||||||
Some(ty.clone())
|
Some(ty.clone())
|
||||||
} else {
|
} else {
|
||||||
@@ -145,22 +145,9 @@ pub(crate) fn expand(
|
|||||||
};
|
};
|
||||||
// `mixed_site` ensures that the data is not accessible to the user-controlled code.
|
// `mixed_site` ensures that the data is not accessible to the user-controlled code.
|
||||||
let data = Ident::new("__data", Span::mixed_site());
|
let data = Ident::new("__data", Span::mixed_site());
|
||||||
let init_fields = init_fields(
|
let init_fields = init_fields(&fields, pinned, &data, &slot);
|
||||||
&fields,
|
|
||||||
pinned,
|
|
||||||
!attrs
|
|
||||||
.iter()
|
|
||||||
.any(|attr| matches!(attr, InitializerAttribute::DisableInitializedFieldAccess)),
|
|
||||||
&data,
|
|
||||||
&slot,
|
|
||||||
);
|
|
||||||
let field_check = make_field_check(&fields, init_kind, &path);
|
let field_check = make_field_check(&fields, init_kind, &path);
|
||||||
Ok(quote! {{
|
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.
|
// Get the data about fields from the supplied type.
|
||||||
// SAFETY: TODO
|
// SAFETY: TODO
|
||||||
let #data = unsafe {
|
let #data = unsafe {
|
||||||
@@ -170,18 +157,15 @@ pub(crate) fn expand(
|
|||||||
#path::#get_data()
|
#path::#get_data()
|
||||||
};
|
};
|
||||||
// Ensure that `#data` really is of type `#data` and help with type inference:
|
// 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,
|
#data,
|
||||||
move |slot| {
|
move |slot| {
|
||||||
{
|
#zeroable_check
|
||||||
// Shadow the structure so it cannot be used to return early.
|
#this
|
||||||
struct __InitOk;
|
#init_fields
|
||||||
#zeroable_check
|
#field_check
|
||||||
#this
|
// SAFETY: we are the `init!` macro that is allowed to call this.
|
||||||
#init_fields
|
Ok(unsafe { ::pin_init::__internal::InitOk::new() })
|
||||||
#field_check
|
|
||||||
}
|
|
||||||
Ok(__InitOk)
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
let init = move |slot| -> ::core::result::Result<(), #error> {
|
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(
|
fn init_fields(
|
||||||
fields: &Punctuated<InitializerField, Token![,]>,
|
fields: &Punctuated<InitializerField, Token![,]>,
|
||||||
pinned: bool,
|
pinned: bool,
|
||||||
generate_initialized_accessors: bool,
|
|
||||||
data: &Ident,
|
data: &Ident,
|
||||||
slot: &Ident,
|
slot: &Ident,
|
||||||
) -> TokenStream {
|
) -> TokenStream {
|
||||||
@@ -260,6 +243,10 @@ fn init_fields(
|
|||||||
});
|
});
|
||||||
// Again span for better diagnostics
|
// Again span for better diagnostics
|
||||||
let write = quote_spanned!(ident.span()=> ::core::ptr::write);
|
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 accessor = if pinned {
|
||||||
let project_ident = format_ident!("__project_{ident}");
|
let project_ident = format_ident!("__project_{ident}");
|
||||||
quote! {
|
quote! {
|
||||||
@@ -272,13 +259,6 @@ fn init_fields(
|
|||||||
unsafe { &mut (*#slot).#ident }
|
unsafe { &mut (*#slot).#ident }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let accessor = generate_initialized_accessors.then(|| {
|
|
||||||
quote! {
|
|
||||||
#(#cfgs)*
|
|
||||||
#[allow(unused_variables)]
|
|
||||||
let #ident = #accessor;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
quote! {
|
quote! {
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
{
|
{
|
||||||
@@ -286,12 +266,18 @@ fn init_fields(
|
|||||||
// SAFETY: TODO
|
// SAFETY: TODO
|
||||||
unsafe { #write(::core::ptr::addr_of_mut!((*#slot).#ident), #value_ident) };
|
unsafe { #write(::core::ptr::addr_of_mut!((*#slot).#ident), #value_ident) };
|
||||||
}
|
}
|
||||||
#accessor
|
#(#cfgs)*
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
let #ident = #accessor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InitializerKind::Init { ident, value, .. } => {
|
InitializerKind::Init { ident, value, .. } => {
|
||||||
// Again span for better diagnostics
|
// Again span for better diagnostics
|
||||||
let init = format_ident!("init", span = value.span());
|
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 (value_init, accessor) = if pinned {
|
||||||
let project_ident = format_ident!("__project_{ident}");
|
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! {
|
quote! {
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
{
|
{
|
||||||
let #init = #value;
|
let #init = #value;
|
||||||
#value_init
|
#value_init
|
||||||
}
|
}
|
||||||
#accessor
|
#(#cfgs)*
|
||||||
|
#[allow(unused_variables)]
|
||||||
|
let #ident = #accessor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
InitializerKind::Code { block: value, .. } => quote! {
|
InitializerKind::Code { block: value, .. } => quote! {
|
||||||
@@ -466,10 +447,6 @@ impl Parse for Initializer {
|
|||||||
if a.path().is_ident("default_error") {
|
if a.path().is_ident("default_error") {
|
||||||
a.parse_args::<DefaultErrorAttribute>()
|
a.parse_args::<DefaultErrorAttribute>()
|
||||||
.map(InitializerAttribute::DefaultError)
|
.map(InitializerAttribute::DefaultError)
|
||||||
} else if a.path().is_ident("disable_initialized_field_access") {
|
|
||||||
a.meta
|
|
||||||
.require_path_only()
|
|
||||||
.map(|_| InitializerAttribute::DisableInitializedFieldAccess)
|
|
||||||
} else {
|
} else {
|
||||||
Err(syn::Error::new_spanned(a, "unknown initializer attribute"))
|
Err(syn::Error::new_spanned(a, "unknown initializer attribute"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,24 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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
|
/// This trait is only implemented via the `#[pin_data]` proc-macro. It is used to facilitate
|
||||||
/// the pin projections within the initializers.
|
/// the pin projections within the initializers.
|
||||||
///
|
///
|
||||||
@@ -68,9 +86,10 @@ pub unsafe trait PinData: Copy {
|
|||||||
type Datee: ?Sized + HasPinData;
|
type Datee: ?Sized + HasPinData;
|
||||||
|
|
||||||
/// Type inference helper function.
|
/// 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
|
where
|
||||||
F: FnOnce(*mut Self::Datee) -> Result<O, E>,
|
F: FnOnce(*mut Self::Datee) -> Result<InitOk, E>,
|
||||||
{
|
{
|
||||||
f
|
f
|
||||||
}
|
}
|
||||||
@@ -98,9 +117,10 @@ pub unsafe trait InitData: Copy {
|
|||||||
type Datee: ?Sized + HasInitData;
|
type Datee: ?Sized + HasInitData;
|
||||||
|
|
||||||
/// Type inference helper function.
|
/// 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
|
where
|
||||||
F: FnOnce(*mut Self::Datee) -> Result<O, E>,
|
F: FnOnce(*mut Self::Datee) -> Result<InitOk, E>,
|
||||||
{
|
{
|
||||||
f
|
f
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user