Commit 26759479 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 69237f8c 592c61f3
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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
+5 −6
Original line number Diff line number Diff line
@@ -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)
+1 −0
Original line number Diff line number Diff line
@@ -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)
+2 −2
Original line number Diff line number Diff line
@@ -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:
+23 −46
Original line number Diff line number Diff line
@@ -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)
                // 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"))
                }
Loading