Skip to content

Commit 2675947

Browse files
committed
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
2 parents 69237f8 + 592c61f commit 2675947

6 files changed

Lines changed: 59 additions & 58 deletions

File tree

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ KBUILD_USERLDFLAGS := $(USERLDFLAGS)
476476
export rust_common_flags := --edition=2021 \
477477
-Zbinary_dep_depinfo=y \
478478
-Astable_features \
479+
-Aunused_features \
479480
-Dnon_ascii_idents \
480481
-Dunsafe_op_in_unsafe_fn \
481482
-Wmissing_docs \
@@ -1113,6 +1114,9 @@ KBUILD_CFLAGS += -fno-builtin-wcslen
11131114
# change __FILE__ to the relative path to the source directory
11141115
ifdef building_out_of_srctree
11151116
KBUILD_CPPFLAGS += -fmacro-prefix-map=$(srcroot)/=
1117+
ifeq ($(call rustc-option-yn, --remap-path-scope=macro),y)
1118+
KBUILD_RUSTFLAGS += --remap-path-prefix=$(srcroot)/= --remap-path-scope=macro
1119+
endif
11161120
endif
11171121

11181122
# include additional Makefiles when needed

rust/Makefile

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,8 @@ doctests_modifiers_workaround := $(rustdoc_modifiers_workaround)$(if $(call rust
148148
quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $<
149149
cmd_rustdoc = \
150150
OBJTREE=$(abspath $(objtree)) \
151-
$(RUSTDOC) $(filter-out $(skip_flags) --remap-path-prefix=%,$(if $(rustdoc_host),$(rust_common_flags),$(rust_flags))) \
151+
$(RUSTDOC) $(filter-out $(skip_flags) --remap-path-prefix=% --remap-path-scope=%, \
152+
$(if $(rustdoc_host),$(rust_common_flags),$(rust_flags))) \
152153
$(rustc_target_flags) -L$(objtree)/$(obj) \
153154
-Zunstable-options --generate-link-to-definition \
154155
--output $(rustdoc_output) \
@@ -334,7 +335,7 @@ quiet_cmd_rustdoc_test_kernel = RUSTDOC TK $<
334335
rm -rf $(objtree)/$(obj)/test/doctests/kernel; \
335336
mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \
336337
OBJTREE=$(abspath $(objtree)) \
337-
$(RUSTDOC) --test $(filter-out --remap-path-prefix=%,$(rust_flags)) \
338+
$(RUSTDOC) --test $(filter-out --remap-path-prefix=% --remap-path-scope=%,$(rust_flags)) \
338339
-L$(objtree)/$(obj) --extern ffi --extern pin_init \
339340
--extern kernel --extern build_error --extern macros \
340341
--extern bindings --extern uapi \
@@ -526,11 +527,9 @@ quiet_cmd_rustc_procmacrolibrary = $(RUSTC_OR_CLIPPY_QUIET) PL $@
526527
cmd_rustc_procmacrolibrary = \
527528
$(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \
528529
$(filter-out $(skip_flags),$(rust_common_flags) $(rustc_target_flags)) \
529-
--emit=dep-info,link --crate-type rlib -O \
530+
--emit=dep-info=$(depfile) --emit=link=$@ --crate-type rlib -O \
530531
--out-dir $(objtree)/$(obj) -L$(objtree)/$(obj) \
531-
--crate-name $(patsubst lib%.rlib,%,$(notdir $@)) $<; \
532-
mv $(objtree)/$(obj)/$(patsubst lib%.rlib,%,$(notdir $@)).d $(depfile); \
533-
sed -i '/^\#/d' $(depfile)
532+
--crate-name $(patsubst lib%.rlib,%,$(notdir $@)) $<
534533

535534
$(obj)/libproc_macro2.rlib: private skip_clippy = 1
536535
$(obj)/libproc_macro2.rlib: private rustc_target_flags = $(proc_macro2-flags)

rust/kernel/cpufreq.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ impl TableBuilder {
401401
/// ```
402402
/// use kernel::cpufreq::{DEFAULT_TRANSITION_LATENCY_NS, Policy};
403403
///
404+
/// #[allow(clippy::double_parens, reason = "False positive before 1.92.0")]
404405
/// fn update_policy(policy: &mut Policy) {
405406
/// policy
406407
/// .set_dvfs_possible_from_any_cpu(true)

rust/kernel/str.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -664,13 +664,13 @@ impl fmt::Write for Formatter<'_> {
664664
///
665665
/// * The first byte of `buffer` is always zero.
666666
/// * The length of `buffer` is at least 1.
667-
pub(crate) struct NullTerminatedFormatter<'a> {
667+
pub struct NullTerminatedFormatter<'a> {
668668
buffer: &'a mut [u8],
669669
}
670670

671671
impl<'a> NullTerminatedFormatter<'a> {
672672
/// Create a new [`Self`] instance.
673-
pub(crate) fn new(buffer: &'a mut [u8]) -> Option<NullTerminatedFormatter<'a>> {
673+
pub fn new(buffer: &'a mut [u8]) -> Option<NullTerminatedFormatter<'a>> {
674674
*(buffer.first_mut()?) = 0;
675675

676676
// INVARIANT:

rust/pin-init/internal/src/init.rs

Lines changed: 23 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ impl InitializerKind {
6262

6363
enum InitializerAttribute {
6464
DefaultError(DefaultErrorAttribute),
65-
DisableInitializedFieldAccess,
6665
}
6766

6867
struct DefaultErrorAttribute {
@@ -86,6 +85,7 @@ pub(crate) fn expand(
8685
let error = error.map_or_else(
8786
|| {
8887
if let Some(default_error) = attrs.iter().fold(None, |acc, attr| {
88+
#[expect(irrefutable_let_patterns)]
8989
if let InitializerAttribute::DefaultError(DefaultErrorAttribute { ty }) = attr {
9090
Some(ty.clone())
9191
} else {
@@ -145,22 +145,9 @@ pub(crate) fn expand(
145145
};
146146
// `mixed_site` ensures that the data is not accessible to the user-controlled code.
147147
let data = Ident::new("__data", Span::mixed_site());
148-
let init_fields = init_fields(
149-
&fields,
150-
pinned,
151-
!attrs
152-
.iter()
153-
.any(|attr| matches!(attr, InitializerAttribute::DisableInitializedFieldAccess)),
154-
&data,
155-
&slot,
156-
);
148+
let init_fields = init_fields(&fields, pinned, &data, &slot);
157149
let field_check = make_field_check(&fields, init_kind, &path);
158150
Ok(quote! {{
159-
// We do not want to allow arbitrary returns, so we declare this type as the `Ok` return
160-
// type and shadow it later when we insert the arbitrary user code. That way there will be
161-
// no possibility of returning without `unsafe`.
162-
struct __InitOk;
163-
164151
// Get the data about fields from the supplied type.
165152
// SAFETY: TODO
166153
let #data = unsafe {
@@ -170,18 +157,15 @@ pub(crate) fn expand(
170157
#path::#get_data()
171158
};
172159
// Ensure that `#data` really is of type `#data` and help with type inference:
173-
let init = ::pin_init::__internal::#data_trait::make_closure::<_, __InitOk, #error>(
160+
let init = ::pin_init::__internal::#data_trait::make_closure::<_, #error>(
174161
#data,
175162
move |slot| {
176-
{
177-
// Shadow the structure so it cannot be used to return early.
178-
struct __InitOk;
179-
#zeroable_check
180-
#this
181-
#init_fields
182-
#field_check
183-
}
184-
Ok(__InitOk)
163+
#zeroable_check
164+
#this
165+
#init_fields
166+
#field_check
167+
// SAFETY: we are the `init!` macro that is allowed to call this.
168+
Ok(unsafe { ::pin_init::__internal::InitOk::new() })
185169
}
186170
);
187171
let init = move |slot| -> ::core::result::Result<(), #error> {
@@ -236,7 +220,6 @@ fn get_init_kind(rest: Option<(Token![..], Expr)>, dcx: &mut DiagCtxt) -> InitKi
236220
fn init_fields(
237221
fields: &Punctuated<InitializerField, Token![,]>,
238222
pinned: bool,
239-
generate_initialized_accessors: bool,
240223
data: &Ident,
241224
slot: &Ident,
242225
) -> TokenStream {
@@ -260,6 +243,10 @@ fn init_fields(
260243
});
261244
// Again span for better diagnostics
262245
let write = quote_spanned!(ident.span()=> ::core::ptr::write);
246+
// NOTE: the field accessor ensures that the initialized field is properly aligned.
247+
// Unaligned fields will cause the compiler to emit E0793. We do not support
248+
// unaligned fields since `Init::__init` requires an aligned pointer; the call to
249+
// `ptr::write` below has the same requirement.
263250
let accessor = if pinned {
264251
let project_ident = format_ident!("__project_{ident}");
265252
quote! {
@@ -272,26 +259,25 @@ fn init_fields(
272259
unsafe { &mut (*#slot).#ident }
273260
}
274261
};
275-
let accessor = generate_initialized_accessors.then(|| {
276-
quote! {
277-
#(#cfgs)*
278-
#[allow(unused_variables)]
279-
let #ident = #accessor;
280-
}
281-
});
282262
quote! {
283263
#(#attrs)*
284264
{
285265
#value_prep
286266
// SAFETY: TODO
287267
unsafe { #write(::core::ptr::addr_of_mut!((*#slot).#ident), #value_ident) };
288268
}
289-
#accessor
269+
#(#cfgs)*
270+
#[allow(unused_variables)]
271+
let #ident = #accessor;
290272
}
291273
}
292274
InitializerKind::Init { ident, value, .. } => {
293275
// Again span for better diagnostics
294276
let init = format_ident!("init", span = value.span());
277+
// NOTE: the field accessor ensures that the initialized field is properly aligned.
278+
// Unaligned fields will cause the compiler to emit E0793. We do not support
279+
// unaligned fields since `Init::__init` requires an aligned pointer; the call to
280+
// `ptr::write` below has the same requirement.
295281
let (value_init, accessor) = if pinned {
296282
let project_ident = format_ident!("__project_{ident}");
297283
(
@@ -326,20 +312,15 @@ fn init_fields(
326312
},
327313
)
328314
};
329-
let accessor = generate_initialized_accessors.then(|| {
330-
quote! {
331-
#(#cfgs)*
332-
#[allow(unused_variables)]
333-
let #ident = #accessor;
334-
}
335-
});
336315
quote! {
337316
#(#attrs)*
338317
{
339318
let #init = #value;
340319
#value_init
341320
}
342-
#accessor
321+
#(#cfgs)*
322+
#[allow(unused_variables)]
323+
let #ident = #accessor;
343324
}
344325
}
345326
InitializerKind::Code { block: value, .. } => quote! {
@@ -466,10 +447,6 @@ impl Parse for Initializer {
466447
if a.path().is_ident("default_error") {
467448
a.parse_args::<DefaultErrorAttribute>()
468449
.map(InitializerAttribute::DefaultError)
469-
} else if a.path().is_ident("disable_initialized_field_access") {
470-
a.meta
471-
.require_path_only()
472-
.map(|_| InitializerAttribute::DisableInitializedFieldAccess)
473450
} else {
474451
Err(syn::Error::new_spanned(a, "unknown initializer attribute"))
475452
}

rust/pin-init/src/__internal.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,24 @@ where
4646
}
4747
}
4848

49+
/// Token type to signify successful initialization.
50+
///
51+
/// Can only be constructed via the unsafe [`Self::new`] function. The initializer macros use this
52+
/// token type to prevent returning `Ok` from an initializer without initializing all fields.
53+
pub struct InitOk(());
54+
55+
impl InitOk {
56+
/// Creates a new token.
57+
///
58+
/// # Safety
59+
///
60+
/// This function may only be called from the `init!` macro in `../internal/src/init.rs`.
61+
#[inline(always)]
62+
pub unsafe fn new() -> Self {
63+
Self(())
64+
}
65+
}
66+
4967
/// This trait is only implemented via the `#[pin_data]` proc-macro. It is used to facilitate
5068
/// the pin projections within the initializers.
5169
///
@@ -68,9 +86,10 @@ pub unsafe trait PinData: Copy {
6886
type Datee: ?Sized + HasPinData;
6987

7088
/// Type inference helper function.
71-
fn make_closure<F, O, E>(self, f: F) -> F
89+
#[inline(always)]
90+
fn make_closure<F, E>(self, f: F) -> F
7291
where
73-
F: FnOnce(*mut Self::Datee) -> Result<O, E>,
92+
F: FnOnce(*mut Self::Datee) -> Result<InitOk, E>,
7493
{
7594
f
7695
}
@@ -98,9 +117,10 @@ pub unsafe trait InitData: Copy {
98117
type Datee: ?Sized + HasInitData;
99118

100119
/// Type inference helper function.
101-
fn make_closure<F, O, E>(self, f: F) -> F
120+
#[inline(always)]
121+
fn make_closure<F, E>(self, f: F) -> F
102122
where
103-
F: FnOnce(*mut Self::Datee) -> Result<O, E>,
123+
F: FnOnce(*mut Self::Datee) -> Result<InitOk, E>,
104124
{
105125
f
106126
}

0 commit comments

Comments
 (0)