Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+59 -58
+4
Makefile
··· 476 476 export rust_common_flags := --edition=2021 \ 477 477 -Zbinary_dep_depinfo=y \ 478 478 -Astable_features \ 479 + -Aunused_features \ 479 480 -Dnon_ascii_idents \ 480 481 -Dunsafe_op_in_unsafe_fn \ 481 482 -Wmissing_docs \ ··· 1114 1113 # change __FILE__ to the relative path to the source directory 1115 1114 ifdef building_out_of_srctree 1116 1115 KBUILD_CPPFLAGS += -fmacro-prefix-map=$(srcroot)/= 1116 + ifeq ($(call rustc-option-yn, --remap-path-scope=macro),y) 1117 + KBUILD_RUSTFLAGS += --remap-path-prefix=$(srcroot)/= --remap-path-scope=macro 1118 + endif 1117 1119 endif 1118 1120 1119 1121 # include additional Makefiles when needed
+5 -6
rust/Makefile
··· 148 148 quiet_cmd_rustdoc = RUSTDOC $(if $(rustdoc_host),H, ) $< 149 149 cmd_rustdoc = \ 150 150 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))) \ 152 153 $(rustc_target_flags) -L$(objtree)/$(obj) \ 153 154 -Zunstable-options --generate-link-to-definition \ 154 155 --output $(rustdoc_output) \ ··· 335 334 rm -rf $(objtree)/$(obj)/test/doctests/kernel; \ 336 335 mkdir -p $(objtree)/$(obj)/test/doctests/kernel; \ 337 336 OBJTREE=$(abspath $(objtree)) \ 338 - $(RUSTDOC) --test $(filter-out --remap-path-prefix=%,$(rust_flags)) \ 337 + $(RUSTDOC) --test $(filter-out --remap-path-prefix=% --remap-path-scope=%,$(rust_flags)) \ 339 338 -L$(objtree)/$(obj) --extern ffi --extern pin_init \ 340 339 --extern kernel --extern build_error --extern macros \ 341 340 --extern bindings --extern uapi \ ··· 527 526 cmd_rustc_procmacrolibrary = \ 528 527 $(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \ 529 528 $(filter-out $(skip_flags),$(rust_common_flags) $(rustc_target_flags)) \ 530 - --emit=dep-info,link --crate-type rlib -O \ 529 + --emit=dep-info=$(depfile) --emit=link=$@ --crate-type rlib -O \ 531 530 --out-dir $(objtree)/$(obj) -L$(objtree)/$(obj) \ 532 - --crate-name $(patsubst lib%.rlib,%,$(notdir $@)) $<; \ 533 - mv $(objtree)/$(obj)/$(patsubst lib%.rlib,%,$(notdir $@)).d $(depfile); \ 534 - sed -i '/^\#/d' $(depfile) 531 + --crate-name $(patsubst lib%.rlib,%,$(notdir $@)) $< 535 532 536 533 $(obj)/libproc_macro2.rlib: private skip_clippy = 1 537 534 $(obj)/libproc_macro2.rlib: private rustc_target_flags = $(proc_macro2-flags)
+1
rust/kernel/cpufreq.rs
··· 401 401 /// ``` 402 402 /// use kernel::cpufreq::{DEFAULT_TRANSITION_LATENCY_NS, Policy}; 403 403 /// 404 + /// #[allow(clippy::double_parens, reason = "False positive before 1.92.0")] 404 405 /// fn update_policy(policy: &mut Policy) { 405 406 /// policy 406 407 /// .set_dvfs_possible_from_any_cpu(true)
+2 -2
rust/kernel/str.rs
··· 664 664 /// 665 665 /// * The first byte of `buffer` is always zero. 666 666 /// * The length of `buffer` is at least 1. 667 - pub(crate) struct NullTerminatedFormatter<'a> { 667 + pub struct NullTerminatedFormatter<'a> { 668 668 buffer: &'a mut [u8], 669 669 } 670 670 671 671 impl<'a> NullTerminatedFormatter<'a> { 672 672 /// 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>> { 674 674 *(buffer.first_mut()?) = 0; 675 675 676 676 // INVARIANT:
+23 -46
rust/pin-init/internal/src/init.rs
··· 62 62 63 63 enum InitializerAttribute { 64 64 DefaultError(DefaultErrorAttribute), 65 - DisableInitializedFieldAccess, 66 65 } 67 66 68 67 struct DefaultErrorAttribute { ··· 85 86 let error = error.map_or_else( 86 87 || { 87 88 if let Some(default_error) = attrs.iter().fold(None, |acc, attr| { 89 + #[expect(irrefutable_let_patterns)] 88 90 if let InitializerAttribute::DefaultError(DefaultErrorAttribute { ty }) = attr { 89 91 Some(ty.clone()) 90 92 } else { ··· 145 145 }; 146 146 // `mixed_site` ensures that the data is not accessible to the user-controlled code. 147 147 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); 157 149 let field_check = make_field_check(&fields, init_kind, &path); 158 150 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 - 164 151 // Get the data about fields from the supplied type. 165 152 // SAFETY: TODO 166 153 let #data = unsafe { ··· 157 170 #path::#get_data() 158 171 }; 159 172 // Ensure that `#data` really is of type `#data` and help with type inference: 160 - let init = ::pin_init::__internal::#data_trait::make_closure::<_, __InitOk, #error>( 173 + let init = ::pin_init::__internal::#data_trait::make_closure::<_, #error>( 161 174 #data, 162 175 move |slot| { 163 - { 164 - // Shadow the structure so it cannot be used to return early. 165 - struct __InitOk; 166 - #zeroable_check 167 - #this 168 - #init_fields 169 - #field_check 170 - } 171 - Ok(__InitOk) 176 + #zeroable_check 177 + #this 178 + #init_fields 179 + #field_check 180 + // SAFETY: we are the `init!` macro that is allowed to call this. 181 + Ok(unsafe { ::pin_init::__internal::InitOk::new() }) 172 182 } 173 183 ); 174 184 let init = move |slot| -> ::core::result::Result<(), #error> { ··· 220 236 fn init_fields( 221 237 fields: &Punctuated<InitializerField, Token![,]>, 222 238 pinned: bool, 223 - generate_initialized_accessors: bool, 224 239 data: &Ident, 225 240 slot: &Ident, 226 241 ) -> TokenStream { ··· 243 260 }); 244 261 // Again span for better diagnostics 245 262 let write = quote_spanned!(ident.span()=> ::core::ptr::write); 263 + // NOTE: the field accessor ensures that the initialized field is properly aligned. 264 + // Unaligned fields will cause the compiler to emit E0793. We do not support 265 + // unaligned fields since `Init::__init` requires an aligned pointer; the call to 266 + // `ptr::write` below has the same requirement. 246 267 let accessor = if pinned { 247 268 let project_ident = format_ident!("__project_{ident}"); 248 269 quote! { ··· 259 272 unsafe { &mut (*#slot).#ident } 260 273 } 261 274 }; 262 - let accessor = generate_initialized_accessors.then(|| { 263 - quote! { 264 - #(#cfgs)* 265 - #[allow(unused_variables)] 266 - let #ident = #accessor; 267 - } 268 - }); 269 275 quote! { 270 276 #(#attrs)* 271 277 { ··· 266 286 // SAFETY: TODO 267 287 unsafe { #write(::core::ptr::addr_of_mut!((*#slot).#ident), #value_ident) }; 268 288 } 269 - #accessor 289 + #(#cfgs)* 290 + #[allow(unused_variables)] 291 + let #ident = #accessor; 270 292 } 271 293 } 272 294 InitializerKind::Init { ident, value, .. } => { 273 295 // Again span for better diagnostics 274 296 let init = format_ident!("init", span = value.span()); 297 + // NOTE: the field accessor ensures that the initialized field is properly aligned. 298 + // Unaligned fields will cause the compiler to emit E0793. We do not support 299 + // unaligned fields since `Init::__init` requires an aligned pointer; the call to 300 + // `ptr::write` below has the same requirement. 275 301 let (value_init, accessor) = if pinned { 276 302 let project_ident = format_ident!("__project_{ident}"); 277 303 ( ··· 312 326 }, 313 327 ) 314 328 }; 315 - let accessor = generate_initialized_accessors.then(|| { 316 - quote! { 317 - #(#cfgs)* 318 - #[allow(unused_variables)] 319 - let #ident = #accessor; 320 - } 321 - }); 322 329 quote! { 323 330 #(#attrs)* 324 331 { 325 332 let #init = #value; 326 333 #value_init 327 334 } 328 - #accessor 335 + #(#cfgs)* 336 + #[allow(unused_variables)] 337 + let #ident = #accessor; 329 338 } 330 339 } 331 340 InitializerKind::Code { block: value, .. } => quote! { ··· 447 466 if a.path().is_ident("default_error") { 448 467 a.parse_args::<DefaultErrorAttribute>() 449 468 .map(InitializerAttribute::DefaultError) 450 - } else if a.path().is_ident("disable_initialized_field_access") { 451 - a.meta 452 - .require_path_only() 453 - .map(|_| InitializerAttribute::DisableInitializedFieldAccess) 454 469 } else { 455 470 Err(syn::Error::new_spanned(a, "unknown initializer attribute")) 456 471 }
+24 -4
rust/pin-init/src/__internal.rs
··· 46 46 } 47 47 } 48 48 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 + 49 67 /// This trait is only implemented via the `#[pin_data]` proc-macro. It is used to facilitate 50 68 /// the pin projections within the initializers. 51 69 /// ··· 86 68 type Datee: ?Sized + HasPinData; 87 69 88 70 /// Type inference helper function. 89 - fn make_closure<F, O, E>(self, f: F) -> F 71 + #[inline(always)] 72 + fn make_closure<F, E>(self, f: F) -> F 90 73 where 91 - F: FnOnce(*mut Self::Datee) -> Result<O, E>, 74 + F: FnOnce(*mut Self::Datee) -> Result<InitOk, E>, 92 75 { 93 76 f 94 77 } ··· 117 98 type Datee: ?Sized + HasInitData; 118 99 119 100 /// Type inference helper function. 120 - fn make_closure<F, O, E>(self, f: F) -> F 101 + #[inline(always)] 102 + fn make_closure<F, E>(self, f: F) -> F 121 103 where 122 - F: FnOnce(*mut Self::Datee) -> Result<O, E>, 104 + F: FnOnce(*mut Self::Datee) -> Result<InitOk, E>, 123 105 { 124 106 f 125 107 }